快速掌握 React 基础入门: 一个完整的指南(三)

简介: 快速掌握 React 基础入门: 一个完整的指南

快速掌握 React 基础入门: 一个完整的指南(二)https://developer.aliyun.com/article/1426133


C. Updating 阶段

Updating 阶段是指一个已经挂载的组件在更新时的过程,更新可以由组件自身的 setState 方法、forceUpdate 方法,或父组件的重新渲染触发。

在 Updating 阶段,React 会自动调用以下生命周期函数(按照调用顺序):

  1. static getDerivedStateFromProps(props, state):静态函数,该函数会在虚拟 DOM 处理之前被调用,用于更新组件的状态。与 Mounting 阶段的调用方式相同。
  2. shouldComponentUpdate(nextProps, nextState):更新函数,用于决定组件是否需要更新。返回一个布尔值,如果返回 true,则执行更新操作,否则不进行更新。默认返回 true,即总是更新。
  3. render():渲染函数,返回组件的虚拟 DOM,用于显示在页面上。
  4. getSnapshotBeforeUpdate(prevProps, prevState):静态函数,用于获取组件更新前的 DOM 状态。可以在此函数中保存一些 DOM 状态,并在 componentDidUpdate 中恢复这些状态。
  5. componentDidUpdate(prevProps, prevState, snapshot):更新函数,用于在组件更新后进行一些额外的操作,例如重新计算 DOM 元素的位置、滚动条的位置等。

示例代码:

import React, { Component } from 'react';
class Example extends Component {
  constructor(props) {
    super(props);
    this.state = { value: 'Hello World' };
  }
  static getDerivedStateFromProps(props, state) {
    console.log('getDerivedStateFromProps', props, state);
    return null;
  }
  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate', nextProps, nextState);
    return true;
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
    console.log('getSnapshotBeforeUpdate', prevProps, prevState);
    return 'snapshot';
  }
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('componentDidUpdate', prevProps, prevState, snapshot);
  }
  handleClick = () => {
    this.setState({ value: 'Hello React' });
  };
  render() {
    console.log('render');
    return (
      <div>
        <p>{this.state.value}</p>
        <button onClick={this.handleClick}>Click me</button>
      </div>
    );
  }
}
export default Example;

在这个例子中,我们为 Example 组件添加了一个按钮,当用户点击按钮时,会调用 handleClick 方法,将组件的 value 状态更新为 'Hello React'。此时,React 会自动调用 Updating 阶段的生命周期函数。

当用户点击按钮时,React 首先会调用 getDerivedStateFromProps 函数,返回 null。然后,React 会调用 shouldComponentUpdate 函数,返回 true。接着,React 调用 render 函数,更新组件的虚拟 DOM,并显示在页面上。在 render 函数执行完毕后,React 调用 getSnapshotBeforeUpdate 函数,返回字符串 'snapshot'。最后,React 调用 componentDidUpdate 函数,更新完成后,进行一些清理工作和其他操作,例如重新计算 DOM 元素的位置等。

D. Unmounting 阶段

Unmounting 阶段是指组件从页面中被卸载的过程,不再被渲染到页面上。卸载可能是由父组件的重新渲染、组件自身的 setState 方法、forceUpdate 方法,或使用 React 的 ReactDOM.unmountComponentAtNode 方法触发。

在 Unmounting 阶段,React 会自动调用以下生命周期函数(按照调用顺序):

  1. componentWillUnmount():卸载函数,用于在组件被卸载前进行清理操作,例如取消订阅、清除定时器等。

示例代码:

import React, { Component } from 'react';
class Example extends Component {
  constructor(props) {
    super(props);
    this.state = { value: 'Hello World' };
  }
  componentWillUnmount() {
    console.log('componentWillUnmount');
  }
  render() {
    console.log('render');
    return (
      <div>
        <p>{this.state.value}</p>
      </div>
    );
  }
}
export default Example;

在这个例子中,我们只实现了 componentWillUnmount 函数,并在组件卸载前输出了一条信息。当组件被卸载时,React 会自动调用该函数,进行清理操作。

需要注意的是,在卸载阶段,组件不会再被更新渲染到 DOM 中,因此在卸载阶段的生命周期函数中不能通过 setState 方法更新组件的状态,这样会导致 React 报错。

VIII. React 中的列表和 keys

在 React 中渲染列表时,可以使用 Array.map 方法进行遍历渲染。有时候,我们需要在渲染列表的时候给每个列表项分配一个唯一的标识,这个标识称为“key”。

React中使用key来标记列表项的唯一性,它可以帮助 React 快速判断出哪些列表项需要更新,从而提高操作性能。

在 React 中使用 key 的方式很简单,例如:

const listItems = items.map(item => (
  <li key={item.id}>
    {item.text}
  </li>
));
return (
  <ul>
    {listItems}
  </ul>
);

在上述代码中,我们使用了数组的 map 方法将 items 数组转成了一个列表,并给每个列表项分配了一个唯一的 key,React 会根据列表项的 key 来判断哪些列表项需要更新,哪些可以复用。这种方式避免了不必要的 DOM 操作,提高了操作性能。

需要注意的是,key 必须是唯一、稳定且可预测的,不能使用数组的索引作为 key,因为当数组顺序发生变化时,会导致 key 不再唯一,从而使 React 在渲染时出现问题。

另外,key 只是在兄弟节点之间必须是唯一的,它们不需要在全局唯一。如果列表项的 id 是全局唯一的,那么可以使用 id 作为 key。如果没有全局唯一的标识,可以使用组合的方式,例如使用 [item.id, index] 作为 key。

总结一下:

  • 在 React 中使用 key 来标记列表项的唯一性,可以提高操作性能。
  • key 必须是唯一、稳定且可预测的,不能使用数组的索引作为 key。
  • key 只需要在兄弟节点之间是唯一的,不需要在全局唯一。

IX. 条件渲染

在 React 中,可以使用条件渲染来根据组件的状态来显示或隐藏组件。条件渲染是指根据条件来决定是否渲染组件或组件的一部分。

React 有两种方式来实现条件渲染:

1. 使用条件运算符

在组件的 render 函数中,可以使用条件运算符 ? : 来根据条件渲染组件或组件的一部分,例如:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isLoggedIn: false };
  }
  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        {isLoggedIn ? (
          <UserGreeting />
        ) : (
          <GuestGreeting />
        )}
      </div>
    );
  }
}
function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

在上述代码中,根据 isLoggedIn 状态的值来渲染 UserGreetingGuestGreeting

2. 使用 && 运算符

在组件的 render 函数中,可以使用 && 运算符来根据条件渲染组件或组件的一部分,例如:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isLoggedIn: false };
  }
  render() {
    const isLoggedIn = this.state.isLoggedIn;
    return (
      <div>
        {isLoggedIn && <UserGreeting />}
        {!isLoggedIn && <GuestGreeting />}
      </div>
    );
  }
}

在上述代码中,根据 isLoggedIn 状态的值来渲染 UserGreetingGuestGreeting,这里使用了 &&! 运算符。

总结一下:

  • 条件渲染是指根据条件来决定是否渲染组件或组件的一部分。
  • React 可以使用条件运算符 ? :&& 运算符来实现条件渲染。
  • 条件渲染可以根据组件的状态来显示或隐藏组件,可以提高组件的动态性和灵活性。

X. React Hooks

A. useEffect

useEffect 是 React 16.8 之后新增的 Hook,它可以让函数组件具有类似于类组件的生命周期钩子函数。useEffect 接收一个回调函数和一个依赖数组作为参数,每当组件渲染时,React 会根据依赖数组中的值来决定是否执行回调函数。

useEffect 的使用方式如下:

import React, { useEffect } from 'react';
function Example() {
  useEffect(() => {
    // 在组件挂载和更新时会被调用
    console.log('componentDidMount and componentDidUpdate');
    return () => {
      // 在组件卸载和更新时会被调用
      console.log('componentWillUnmount and componentDidUpdate');
    };
  }, [props.value]); // 仅在 props.value 发生变化时执行回调函数
  return <div>{props.value}</div>;
}

在这个例子中,我们定义了一个函数组件 Example,并使用了 useEffect Hook。useEffect 接收一个回调函数和一个依赖数组作为参数,函数组件每次渲染时都会执行回调函数。当依赖数组中的值发生变化时,React 会重新执行回调函数。如果依赖数组为空,则函数组件只会在挂载和卸载时执行回调函数。

回调函数可以返回一个清理函数,用于在组件卸载前执行一些清理操作,例如取消订阅、关闭定时器等等。

需要注意的是,由于 useEffect 是在组件函数内部定义的,因此回调函数可以调用父组件中的 state 和 props,而不需要使用类组件中的生命周期函数来访问它们。

总结一下:

  • useEffect 是 React 16.8 之后新增的 Hook。
  • useEffect 接收一个回调函数和一个依赖数组作为参数,函数组件每次渲染时都会执行回调函数。
  • 当依赖数组中的值发生变化时,React 会重新执行回调函数。
  • 回调函数可以返回一个清理函数,用于在组件卸载前执行一些清理操作。
  • 由于 useEffect 是在组件函数内部定义的,因此回调函数可以调用父组件中的 state 和 props。

B. useState

useState 是 React 16.8.0 之后推出的一个 Hook 函数,它可以让函数组件具有状态(state)。

useState 的使用方式如下:

import { useState } from 'react';
function Example() {
  // 在函数组件中使用 useState Hook 来定义状态
  const [count, setCount] = useState(0);
  function handleClick() {
    // 使用 setCount 函数来更新状态
    setCount(count + 1);
  }
  return (
    <div>
      <p>You clicked {count} times.</p>
      <button onClick={handleClick}>Click Me</button>
    </div>
  );
}

在这个例子中,我们定义了一个函数组件 Example,并使用了 useState Hook 来定义状态。useState 接收一个状态的初始值作为参数,并返回一个数组,第一个元素是当前状态的值,第二个元素是用于更新状态的函数。每当 setCount 函数被调用时,React 会自动重新渲染函数组件,并把新的状态值传递给组件。在更新状态时,不需要手动去合并旧状态和新状态,React 会自动处理。

需要注意的是,由于 useState 是在组件函数内部定义的,因此可以在同一个组件函数中多次使用 useState 来定义多个状态。

总结一下:

  • useState 是 React 16.8 之后推出的 Hook 函数,可以让函数组件具有状态(state)。
  • useState 接收一个状态的初始值作为参数,并返回一个数组,第一个元素是当前状态的值,第二个元素是用于更新状态的函数。
  • 在更新状态时,不需要手动去合并旧状态和新状态,React 会自动处理。
  • useState 是在组件函数内部定义的,因此可以在同一个组件函数中多次使用 useState 来定义多个状态。

C. useContext

useContext 是 React 16.8.0 之后推出的 Hook 函数,它可以让函数组件消费 Context

在 React 中,Context 可以让我们在组件树中共享数据,无需一级一级手动传递数据。当应用程序规模较大时,Context 可以非常有用,帮助我们简化数据的传递和管理。

使用 useContext 可以让我们更轻松地从 Context 中读取数据。通常,我们需要首先创建一个 Context 对象,然后将其传递给使用它的组件,使用 useContext 函数从 Context 中读取数据。

接下来给出一个使用 useContext 函数的例子:

import React, { useContext } from 'react';
const UserContext = React.createContext({ name: 'Guest' });
function Example() {
  const user = useContext(UserContext);
  return (
    <div>
      <p>Hello, {user.name}!</p>
    </div>
  );
}

在上述例子中,我们创建了一个名为 UserContext 的 Context 对象,并提供一个默认值 { name: 'Guest' }。然后,在 Example 组件中使用 useContext 函数从 UserContext 中读取数据,因此在组件中可以直接访问 user 对象,不需要通过 props 层层传递数据。

需要注意的是,在使用 useContext 时,需要将 UserContext 对象作为参数传递给 useContext 函数,例如:

const user = useContext(UserContext);

总结一下:

  • useContext 是 React 16.8 之后推出的 Hook 函数,可以让函数组件消费 Context
  • Context 可以让我们在组件树中共享数据,无需一级一级手动传递数据。
  • 使用 useContext 函数可以更轻松地从 Context 中读取数据。
  • 在使用 useContext 时,需要将 Context 对象作为参数传递给 useContext 函数。

D. useReducer

useReducer 是 React 16.8.0 之后推出的 Hook 函数,可以方便地管理组件的状态。useReduceruseState 类似,都可以让函数组件管理状态,但 useReducer 更适用于复杂的状态逻辑。

useReducer 接收一个“reducer”函数和一个初始状态作为参数,返回一个数组,第一个元素是当前状态值,第二个元素是用于更新状态的 dispatch 函数。

下面是一个使用 useReducer 的例子:

import React, { useReducer } from 'react';
const initialState = { count: 0 };
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}
function Example() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
    </div>
  );
}

在这个例子中,我们定义了一个初始状态 { count: 0 } 和一个“reducer”函数 reducer,然后在 Example 组件中使用了 useReducer 来定义状态。useReducer 的第一个参数是 reducer 函数,第二个参数是初始状态。

在组件中可以通过 dispatch 函数来触发状态的更新,通过传入一个 action 对象来描述状态的变化。在 reducer 函数中根据 action.type 的值来更新状态,并返回一个新的状态对象。

需要注意的是,在使用 useReducer 时,尽量避免直接修改原有状态对象,应该返回一个新的状态对象。

总结一下:

  • useReducer 是 React 16.8 之后推出的 Hook 函数,可以方便地管理组件的状态。
  • useReducer 接收一个“reducer”函数和一个初始状态作为参数,返回一个数组。第一个元素是当前状态值,第二个元素是用于更新状态的 dispatch 函数。
  • useReducer 中,通过 dispatch 函数来触发状态的更新,在 reducer 函数中根据 action.type 的值来更新状态,并返回一个新的状态对象。
相关文章
|
5月前
|
前端开发 JavaScript 开发者
React:JSX语法入门
React:JSX语法入门
64 0
|
2月前
|
XML JavaScript 前端开发
React Jsx语法入门
【8月更文挑战第13天】React Jsx语法入门
35 4
|
19天前
|
移动开发 前端开发 JavaScript
构建高效跨平台移动应用:React Native入门指南
【8月更文挑战第47天】在移动开发领域,React Native凭借其跨平台特性和高效的开发模式赢得了开发者的青睐。本文将通过一个简易的待办事项应用实例,带领读者快速入门React Native,并展示如何利用JavaScript和React框架构建具有原生性能的应用。我们将探讨环境配置、界面布局、状态管理和数据流,以及如何打包和发布您的应用。准备好,让我们开始React Native之旅!
57 20
|
1月前
|
前端开发 JavaScript
React技术栈-React UI之ant-design使用入门
关于React技术栈中使用ant-design库的入门教程,包括了创建React应用、搭建开发环境、配置按需加载、编写和运行代码的步骤,以及遇到错误的解决方法。
24 2
React技术栈-React UI之ant-design使用入门
|
1月前
|
XML 存储 前端开发
React 基础入门
【9月更文挑战第1天】本文详细介绍了由Facebook开发的JavaScript库React,涵盖环境搭建、基本概念、常见问题及解决方案。首先,通过安装Node.js、npm和Create React App快速搭建开发环境;接着,讲解了JSX、组件(包括函数和类组件)、state和props等核心概念;最后,针对JSX语法错误、state异步更新及props与state混淆等问题提供了具体的解决方法和示例代码,帮助读者更好地理解和应用React。
21 2
|
2月前
|
JavaScript 前端开发 容器
React基础入门之虚拟dom【一】
【8月更文挑战第14天】React基础入门之虚拟dom
33 0
React基础入门之虚拟dom【一】
|
2月前
|
前端开发 人机交互
langchain 入门指南 - ReAct 模式
langchain 入门指南 - ReAct 模式
52 1
|
2月前
|
移动开发 前端开发 JavaScript
构建高效跨平台移动应用:React Native入门指南
【8月更文挑战第31天】 在移动开发领域,React Native凭借其跨平台特性和高效的开发模式赢得了开发者的青睐。本文将通过一个简易的待办事项应用实例,带领读者快速入门React Native,并展示如何利用JavaScript和React框架构建具有原生性能的应用。我们将探讨环境配置、界面布局、状态管理和数据流,以及如何打包和发布您的应用。准备好,让我们开始React Native之旅!
|
2月前
|
开发者
告别繁琐代码,JSF标签库带你走进高效开发的新时代!
【8月更文挑战第31天】JSF(JavaServer Faces)标准标签库为页面开发提供了大量组件标签,如`&lt;h:inputText&gt;`、`&lt;h:dataTable&gt;`等,简化代码、提升效率并确保稳定性。本文通过示例展示如何使用这些标签实现常见功能,如创建登录表单和展示数据列表,帮助开发者更高效地进行Web应用开发。
32 0
|
2月前
|
前端开发 JavaScript UED
🎬JSF 与 Ajax:打造瞬间响应的魔法界面!🚀 用户输入即刻,数据交互如梦幻泡影般呈现!
【8月更文挑战第31天】在现代Web应用中,异步数据交互是提升用户体验的关键。JavaServer Faces (JSF) 作为标准Java Web框架,结合Ajax技术,可轻松实现页面异步更新与数据交互。本文通过示例代码介绍如何在JSF中使用Ajax组件(如`f:ajax`)及后端处理方法实现异步功能,并结合JavaScript处理复杂交互,帮助开发者提升Web应用体验。
34 0