本系列文章 "React 状态管理" 也是希望能帮助到大家了解不同状态管理方案(React 官方本身提供的及社区的一些库)能做的事情有哪些及优略点。
成都创新互联专注于琅琊网站建设服务及定制,我们拥有丰富的企业做网站经验。 热诚为您提供琅琊营销型网站建设,琅琊网站制作、琅琊网页设计、琅琊网站官网定制、小程序制作服务,打造琅琊网络公司原创品牌,更为您提供琅琊网站排名全网营销落地服务。
本篇先从 React 本身提供的组件状态管理开始。React 的组件状态分为类组件时代的 和当下函数组件的 hooks API 管理数据状态。
State类组件将组件内所有的状态放在一个 state 中管理: 获取状态数据、 更新状态数据。
import React from 'react';
class State extends React.Component {
constructor() {
super();
this.state = {
count: 0,
}
}
render() {
return
count: {this.state.count}
}
}
export default State;
React 16.8 发布后,函数组件成为热门选择,组件状态使用 useState() 函数,相比类组件状态拆分的更细并且每次更新状态变量都是替换而不是合并。
如果更新依赖于先前的状态,可以将函数传递给 setState,并返回一个更新后的值 setState(preState => newState)。 熟悉 Redux 的朋友看起来也许不陌生,该函数是不是更像一个 reducer 函数?
示例:useState 实现计数器增、减、重置。
import { useState } from 'react';
const State = () => {
const [count, setCount] = useState(0);
return
计数器 count: {count}
}
export default State;
刚开始看到 useReducer 时,还联想和 Redux 之间有什么关系?需要注意的是和 Redux 完全不是一个东西,useReducer 是 React Hooks 提供的一个 API,如果熟悉 Redux 可能看起来会更熟悉。
useReducer 是 useState 的替代方案,主要用来处理一些逻辑比较复杂的 state 或 下一个 state 依赖于前一个 state 等。
Example:使用 useReducer 重写上面的计数器示例,可以和上面的 useState 做一个对比。
import { useReducer } from "react"
const COUNT_INCREMENT = 'COUNT_INCREMENT';
const COUNT_DECREMENT = 'COUNT_DECREMENT';
const COUNT_RESET = 'COUNT_RESET';
const initialState = {
count: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case COUNT_INCREMENT:
return { count: state.count + 1 };
case COUNT_DECREMENT:
return { count: state.count - 1 };
case COUNT_RESET:
return { count: initialState.count };
default:
return state;
}
};
const State = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return
计数器 count: {state.count}
}
export default State;
使用 useReducer 实现一个稍微复杂点的功能,例如 Todos,有创建、更新、移除待办事项功能,你可以试想下如果换做 useState 该怎么处理?会不会更麻烦?
在 目录下实现 reducer 需要的逻辑,定义的 initialState 变量、reducer 函数都是为 useReducer 这个 Hook 做准备的,这里的 reducer 函数是一个纯函数。
// src/reducers/todos-reducer.jsx
export const TODO_LIST_ADD = 'TODO_LIST_ADD';
export const TODO_LIST_EDIT = 'TODO_LIST_EDIT';
export const TODO_LIST_REMOVE = 'TODO_LIST_REMOVE';
const randomID = () => Math.floor(Math.random() * 10000);
export const initialState = {
todos: [{ id: randomID(), content: 'todo list' }],
};
const reducer = (state, action) => {
switch (action.type) {
case TODO_LIST_ADD: {
const newTodo = {
id: randomID(),
content: action.payload.content
};
return {
todos: [ ...state.todos, newTodo ],
}
}
case TODO_LIST_EDIT: {
return {
todos: state.todos.map(item => {
const newTodo = { ...item };
if (item.id === action.payload.id) {
newTodo.content = action.payload.content;
}
return newTodo;
})
}
}
case TODO_LIST_REMOVE: {
return {
todos: state.todos.filter(item => item.id !== action.payload.id),
}
}
default: return state;
}
}
export default reducer;
下面进行待办事项组件开发,细分为 TodoAdd、Todo、Todos 三个组件,在 Todos 组件内使用 useReducer 获取组件需要的状态(state)和更新状态的方法(dispatch)。
添加、更新、删除待办事项行为分别在 TodoAdd、Todo 组件中,以下我们使用的是 React 推荐的 组合组件模式,可以通过 props 从父组件传递数据到子组件。
import { useReducer, useState } from "react";
import reducer, { initialState, TODO_LIST_ADD, TODO_LIST_EDIT, TODO_LIST_REMOVE } from "../../reducers/todos-reducer";
const TodoAdd = ({ dispatch }) => {
const [content, setContent] = useState('');
return <>
setContent(e.target.value)} />
>
};
const Todo = ({ todo, dispatch }) => {
const [isEdit, setIsEdit] = useState(false);
const [content, setContent] = useState(todo.content);
return
{
!isEdit ? <>
{todo.content}
> : <>
setContent(e.target.value) } />
>
}
}
const Todos = () => {
const [state, dispatch] = useReducer(reducer, initialState);
return <>
{
state.todos.map(todo =>key={todo.id}
todo={todo}
dispatch={dispatch}
/>)
}
>
}
export default Todos;
useState 适合定义一些单一的状态,useReducer 适合逻辑比较复杂的状态。
一个好的经验法则是:"如果状态是基本的数据类型(字符串、数值型、布尔型)可以选择 useState,如果是数组或对象等其它复杂的类型或复杂逻辑时最好选择 useReducer"。
但是两者都是组件的状态管理,当多个组件协同工作时不得不面对组件间 "数据通信" 问题。
React 组件数据状态流转是一个 "单项数据流" 的理念。简单的组件可以通过 props 传递数据状态,当组件过多时,层层 Props 传递的方式显的就有点过于繁琐了,不易维护。
当前文章:React状态管理—useState和useReducer如何选择?
网页网址:http://www.csdahua.cn/qtweb/news44/532544.html
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网