状态管理在 React 应用程序中至关重要,因为它有助于跟踪应用程序数据。由于用户界面 (UI) 是状态的函数,因此确保应用程序的状态始终是最新的至关重要。在本文中,您将了解如何选择合适的状态管理工具来满足您的应用程序要求。
注意:本文适用于已经对 React 有一定了解但希望基于状态管理为自己的 React 应用程序做出更好选择的开发者。如果您还不了解 React,请查看文档开始学习。
了解状态和状态管理。
基于上述先决条件,您可能已经对 React 有了一些了解。但让我们稍微回忆一下。
什么是国家?
React 中的状态是组件的内存,包含特定于该组件的信息。用编程术语来说,状态是一个 JavaScript 对象,它只包含与组件相关的数据。
如前所述,React 中的 UI 直接受状态影响。状态的变化主要是由于用户交互而发生的,例如按钮单击、鼠标事件、输入操作等。因此,管理应用程序中的状态对于确保用户根据其交互在屏幕上体验最新的界面至关重要。
React 中的状态管理。
当 React 组件的状态发生变化时,会导致组件重新渲染。在此过程中,组件在幕后被销毁并从头开始重建。
大多数 React 应用程序在用户与应用程序交互时都会经历大量的状态更新。使用最好的状态管理技术来增强用户体验非常重要;毕竟,使用无响应的应用程序并不具有吸引力。想象一下,点击 Instagram 应用程序上的“赞”按钮,但它没有响应。很烦人吧?
言归正传,让我们深入了解您可以为项目探索的不同状态管理选项,解释何时以及为何需要每个选项。
React 中的不同状态管理选项。
有许多可用的状态管理选项,但在本文中,我们将介绍一些最常用的选项,以满足从小型到超大的各种规模的应用程序。我们将讨论的选项包括:
- React 内置钩子
- 上下文API
- 第三方库
React 内置钩子用于状态管理
React 提供了内置的钩子来管理功能组件的状态。这些钩子易于使用,非常适合本地状态管理。
本地状态是仅一个组件需要的状态,不会影响任何其他组件。
全局状态是多个组件需要的状态,我们还将在本文后面介绍如何管理它。
使用状态钩子
当然,函数式组件是无状态的,但 React 引入了 useState 钩子,使开发人员能够将状态变量添加到需要它们的组件中。
这个钩子在组件的顶层调用,并传入一个初始状态值,它返回一个当前值的数组和一个 setter 函数。以下是如何使用它的代码示例:
import { useState} from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onclick="{()"> setCount(count + 1)}> Click me </button> </div> ); }
说明
- 初始计数从 0 开始
- 每当单击按钮时都会调用设置计数函数,从而始终使用最新值更新计数变量。
何时使用 useState 挂钩
useState 钩子非常适合在以下情况下管理组件中的状态:
- 本地状态管理:状态仅在单个组件内需要,不需要在多个组件之间共享。
- 简单状态逻辑:状态逻辑很简单,例如切换值、计数器、表单输入和简单条件。
- 有限的组件层次结构:状态不需要深入传递多层组件,这可能会导致道具钻探。
- 小型项目:应用程序没有需要更高级解决方案的广泛状态管理需求。
示例:
- Managing form input values.
- Toggling UI elements (e.g., show/hide).
- Simple counters and trackers.
The useState hook provides a simple and efficient way to handle state for these scenarios, ensuring your components remain manageable and easy to understand.
useReducer Hook
The useReducer hook was introduced by the React team to handle complex state logic or case-sensitive updates. Here are the key parameters you need to keep in mind while using useReducer:
- reducer: This is the function where all the state updating code is executed. It takes the current state and an action as arguments and returns a new state.
- initialArg: This is the initial state that you declare from the onset.
- dispatch: This is the function called in the event handler. It is returned from the useReducer hook and is used to send actions to the reducer.
- state: This is the current state value also returned by the useReducer hook.
Here’s a code example of how to use this hook:
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 Counter() { 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> ); }
Key Takeaways:
- Just like every other hook, useReducer must be called at the top level of the component.
- Every time the dispatch function is called, it triggers the reducer, leading to a state update depending on the action. This causes the component to re-render, maintaining the goal of keeping the UI and the current state in sync.
- You should only specify the action type in the dispatch function and a payload if need be.
When to Use the useReducer Hook
The useReducer hook is ideal for managing state in your components when:
- Complex State Logic: The state logic is complex, involves multiple sub-values, or the next state depends on the previous state.
- State Transition Management: When you need to handle multiple state transitions based on different actions.
Examples of Projects that Require useReducer
Complex forms: A multi-step form in a registration process.Each step of the form collects different data, and the state needs to be managed for all steps, with validation and submission logic.
Advanced to-do-list: A to-do list application with features like adding, removing, editing, and filtering tasks.
E-commerce cart management: An e-commerce site with a shopping cart that handles adding, removing, and updating item quantities.
State Management with Context API
The previously discussed options are great, but they come with a downside: the problem of prop drilling. Prop drilling occurs when a state needs to be passed down through multiple nested components from a parent to a child. This can lead to verbose and hard-to-maintain code, as each intermediary component needs to explicitly pass the state or function down the tree.Global state, which is the state needed by multiple components, becomes particularly challenging to manage with prop drilling.
To solve this problem, React introduced the Context API, which is used for managing global state. The Context API allows you to create a context object that can be accessed by any component within its provider, eliminating the need to pass props through intermediate components.
How to Use the Context API
Here’s a step-by-step guide on how to use it:
-
Create a Context: First, create a context using the createContext function. This creates an object with a Provider and a Consumer.
import React, { createContext } from 'react'; const MyContext = createContext();
-
Provide Context Value: Wrap the components that need access to the context with the Provider component. Pass the value you want to share as a prop to the Provider.
function App() { const [state, setState] = useState("Hello, World!"); return ( <MyContext.Provider value={{ state, setState }}> <ChildComponent /> </MyContext.Provider> ); }
-
Consume Context Value: This Use the context value in the child components by using the useContext hook or the Consumer component.
import React, { useContext } from 'react'; import MyContext from './path-to-context'; function ChildComponent() { const { state, setState } = useContext(MyContext); return ( <div> <p>{state}</p> <button onClick={() => setState("Context API is awesome!")}> Change Text </button> </div> ); }
Example Usage
Here’s a complete example demonstrating how to use the Context API:
import React, { createContext, useState, useContext } from 'react'; // Create a context const MyContext = createContext(); function App() { const [state, setState] = useState("Hello, World!"); return ( <mycontext.provider value="{{" state setstate> <childcomponent></childcomponent> </mycontext.provider> ); } function ChildComponent() { const { state, setState } = useContext(MyContext); return ( <div> <p>{state}</p> <button onclick="{()"> setState("Context API is awesome!")}> Change Text </button> </div> ); } export default App;
Key Takeaways:
- 创建Context:createContext()用于创建Context对象,其中包括Provider和Consumer。
- 提供上下文:Provider 组件用于将当前上下文值传递给需要它的组件树。
- 使用上下文:useContext 钩子在功能组件中使用来访问上下文值。
何时使用上下文 API
Context API 非常适合需要在多个组件之间共享状态或数据而无需在组件树的每个级别传递 props 的场景。当处理全局状态或状态需要由深度嵌套的组件访问时,它特别有用。以下是 Context API 有益的一些具体案例:
-
主题:
- 示例:在整个应用程序中管理主题(浅色或深色模式)。
- 详细信息:主题状态在多个组件之间共享,确保 UI 一致地反映所选主题。
-
用户身份验证:
- 示例:管理用户身份验证状态和用户信息。
- 详细信息:身份验证状态(登录/退出)和用户数据(用户名、角色等)需要通过各种组件访问,例如标题、个人资料页面和受保护的路由。
-
语言本地化:
- 示例:在应用程序中处理多语言支持。
- 详细信息:所选语言状态和翻译数据需要可供整个应用程序的文本渲染组件使用。
-
表单的复杂状态管理:
- 示例:跨多个表单字段和组件共享表单数据和验证状态。
- 详细信息:跨越多个步骤或组件的表单可以从跟踪输入值和验证错误的共享状态中受益。
通过了解何时以及如何使用 Context API,您可以更有效地管理 React 应用程序中的全局状态。这种方法有助于避免 prop 钻探的陷阱,保持代码库清洁和可维护,并有助于创建更健壮和可扩展的 React 应用程序。
用于状态管理的第三方库
第三方状态管理库提供了额外的工具和模式来有效地管理状态,特别是在复杂的应用程序中。这些库通常具有高级功能和优化,可以增强 React 提供的内置状态管理解决方案。一些最流行的第三方状态管理库包括 Redux、MobX、Recoil 和 Zustand。
在本文中,我们将介绍 Redux。如果您需要使用提到的其他人,您可以查看他们的文档;我将在本文末尾添加链接。不要感到不知所措,这些工具中的大多数都非常适合初学者。现在,让我们直接进入 Redux!
使用 Redux 进行状态管理
Redux 是一个第三方状态管理库,通过将所有状态存储在一个称为 store 的中心位置,为 prop 钻探和全局状态管理提供了最佳解决方案。这意味着所有组件都可以独立访问此状态,无论它们在组件树中的位置如何。
这是一个游戏规则改变者,因为随着应用程序变得越来越大并且有更多的状态需要处理,有必要将其抽象到一个地方。这种组织方式使我们的代码更加干净并且调试更加容易。听起来不错,对吧?
请记住,Redux 并不特别限于 React;它是一个独立的库,可以与 Angular、Vue 等其他 JavaScript 框架集成。
如何在 React 中使用 Redux
在我们逐步了解使用 Redux 的过程之前,了解构成 Redux 基础的关键概念非常重要:
- Store: The store is the central repository for an application's state. It holds the entire state tree and provides methods to access and update the state.
- Reducers: Reducers are pure functions that determine how the state changes in response to actions. They take the current state and an action as arguments and return a new state.
- Actions: Actions are plain JavaScript objects that describe what happened in the application. Each action has a type property and may include additional data.
- Action Creators: Action creators are functions that create and return action objects. They encapsulate the action creation logic, making the code more manageable.
- Dispatch: Dispatch is a function provided by the Redux store that sends actions to the store. It triggers reducers to process the action and update the state.
Understanding these concepts is essential to effectively implementing Redux in your React application.
How to Integrate and Use Redux in Your React Project
In this subsection, you will learn a step-by-step approach to integrating Redux with your React projects. We'll use a simple counter-example to illustrate the process. Here are the steps:
Setting up your Project
-
Create a React app with Vite:
npm create vite@latest projectName
-
Navigate into your project directory:
cd projectName
-
Install Redux Toolkit and React-Redux:
npm install @reduxjs/toolkit react-redux
-
Creating the Redux Store: Create a new file src/app/store.js and set up the Redux store:
import { createStore } from 'redux'; import rootReducer from '../features/counter/counterReducer'; const store = createStore(rootReducer); export default store;
-
Creating the Reducer: Create a new directory src/features/counter and inside it, create a file counterReducer.js:
const initialState = { value: 0, }; function counterReducer(state = initialState, action) { switch (action.type) { case 'INCREMENT': return { ...state, value: state.value + 1 }; case 'DECREMENT': return { ...state, value: state.value - 1 }; case 'INCREMENT_BY_AMOUNT': return { ...state, value: state.value + action.payload }; default: return state; } } export default counterReducer;
-
Creating Actions: In the same directory, create a file counterActions.js:
export const increment = () => ({ type: 'INCREMENT', }); export const decrement = () => ({ type: 'DECREMENT', }); export const incrementByAmount = (amount) => ({ type: 'INCREMENT_BY_AMOUNT', payload: amount, });
-
Providing the Store to Your App: Wrap your application with the Redux Provider in src/main.jsx:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import store from './app/store'; import App from './App'; import './index.css'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
-
Connecting React Components to Redux: In your src/App.jsx, use the Redux state and dispatch actions:
import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { increment, decrement, incrementByAmount } from './features/counter/counterActions'; function App() { const count = useSelector((state) => state.value); const dispatch = useDispatch(); return ( <div> <p>Count: {count}</p> <button onClick={() => dispatch(increment())}>+</button> <button onClick={() => dispatch(decrement())}>-</button> <button onClick={() => dispatch(incrementByAmount(2))}>+2</button> </div> ); } export default App;
This is how to use Redux in your React applications. If you need to know more, you can check the documentation. However, Redux has introduced a more optimized way of writing Redux applications with Redux Toolkit (RTK).
Before RTK, the legacy Redux was the only way to use Redux. Now, we have Redux Toolkit with some optimized features, and that is what we will be covering in the next section.
How to Use Redux Toolkit in React
RTK introduces several key concepts that simplify state management. The major ones you need to know are:
Slices: A slice is a collection of Redux reducer logic and actions for a single feature of your application. It streamlines the process of writing reducers and actions into a single unit.
createSlice: This RTK function helps you create a slice, automatically generating action creators and action types. It reduces boilerplate code significantly.
configureStore: This function simplifies the process of creating a Redux store by providing good defaults, including integration with the Redux DevTools Extension and middleware like redux-thunk.
createAsyncThunk: This function is used for handling asynchronous logic. It generates actions and action creators to manage different stages of an asynchronous operation (e.g., pending, fulfilled, and rejected).
Selectors: Functions that extract and derive pieces of state from the store. RTK encourages using selectors to encapsulate and reuse state logic.
RTK Query: An advanced data fetching and caching tool built into RTK. It simplifies handling server-side data, reducing the need for boilerplate code related to data fetching, caching, and synchronization.
Understanding these concepts is essential for effectively implementing Redux Toolkit in your React application.
How to integrate and use Redux Toolkit in your React project
In this subsection, you'll learn a step-by-step approach to integrating Redux Toolkit with your React projects. We’ll use a simple counter example, similar to the one used in the plain Redux example, to highlight the improvements and optimizations Redux Toolkit offers. Here are the steps:
Setting up your Project
-
Create a React app with Vite:
npm create vite@latest projectName
-
Navigate into your project directory:
cd projectName
-
Install Redux Toolkit and React-Redux:
npm install @reduxjs/toolkit react-redux
-
Creating a Redux Slice: Create a new file for your slice (e.g., counterSlice.js):
import { createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { count: 0 }, reducers: { increment: (state) => { state.count += 1; }, decrement: (state) => { state.count -= 1; }, }, }); export const { increment, decrement } = counterSlice.actions; export default counterSlice.reducer;
-
Configuring the Store: Create a new file for your store (e.g., store.js):
import { configureStore } from '@reduxjs/toolkit'; import counterReducer from './counterSlice'; const store = configureStore({ reducer: { counter: counterReducer, }, }); export default store;
-
Providing the Store to Your App: Wrap your app with the Provider component in your main file (e.g., main.js or index.js):
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import store from './store'; import App from './App'; ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
-
Using Redux State and Actions in Your Components: Use the useSelector and useDispatch hooks in your component (e.g., Counter.js):
import React from 'react'; import { useSelector, useDispatch } from 'react-redux'; import { increment, decrement } from './counterSlice'; function Counter() { const count = useSelector((state) => state.counter.count); const dispatch = useDispatch(); return ( <div> <p>{count}</p> <button onClick={() => dispatch(increment())}>+</button> <button onClick={() => dispatch(decrement())}>-</button> </div> ); } export default Counter;
Redux Toolkit (RTK) simplifies and optimizes the traditional Redux setup by reducing boilerplate code and integrating essential tools and best practices. While legacy Redux requires manual configuration and verbose code for actions and reducers, RTK offers a more streamlined approach with utility functions like configureStore, createSlice, and createAsyncThunk.
RTK includes built-in middleware, integrates seamlessly with Redux DevTools, and promotes a standard way of writing Redux logic, making state management in React applications more efficient and maintainable. If you need to use Redux, I recommend using the modern Redux Toolkit, as it is now recommended by Redux. You can check the docs to learn more about RTK.
When to Use Redux
Redux is a powerful state management library, but it isn't always necessary for every React application. Here are some scenarios when using Redux might be beneficial:
-
Complex State Logic:
- When your application has complex state logic that is difficult to manage with React's built-in hooks like useState and useReducer.
- Example: An e-commerce application with multiple product filters, user authentication, and a shopping cart.
-
Global State Management:
- When you have state that needs to be accessed and updated by many components across different parts of your application.
- Example: A user authentication system where user data needs to be accessible throughout the application.
-
Consistent and Predictable State:
- When you need a predictable state container that helps you debug and test your application more easily.
- Example: A large-scale application where you need to maintain and track the state transitions clearly.
-
DevTools Integration:
- When you want to leverage powerful developer tools like Redux DevTools for tracking state changes and debugging.
- Example: During development, Redux DevTools can help in understanding how the state changes in response to actions.
Conclusion
I hope by now you have gained more clarity and insights into choosing the right state management tool for your projects. We have covered tools that cater to both small and extremely large projects. With the knowledge gained from this article, you can now make more informed decisions for your projects. See you next time on another insightful topic.
Further reading and learning
Redux docs
Zustand docs
Mobx docs
Recoil docs
React docs
以上是Reactjs 中的状态管理:为您的项目选择正确的状态管理工具的指南的详细内容。更多信息请关注PHP中文网其他相关文章!

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

WebStorm Mac版
好用的JavaScript开发工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

Dreamweaver Mac版
视觉化网页开发工具

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。