Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to elegantly use react hooks for state management

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

In the process of using react and redux, there has always been a problem, which states need to be placed in redux and which states need to be saved in local state within components. In addition, unreasonable use of redux may lead to confusion in state management. In addition, react hooks provides a better alternative to setState in class for local states of local state. This article mainly starts from the state management, and talks about how to use hooks to manage the state elegantly.

How to use redux

React hooks Management local state

How to solve the Communication between components by react hooks

The original article is in my blog: github.com/fortheallli... Welcome to subscribe

First, how to use redux

First of all, it's important to be clear about why you use redux. If you don't know why you use redux, you can't use redux. First of all, let's look at the nature of redux:

As a state management tool, redux is mainly to solve the problem of communication between components.

Since it is a communication problem between components, it is obviously unreasonable and complex to put the state of all pages into redux.

(1) full use of redux

The author also made this problem in the early days, in the application, no matter what state, according to the page-level routing split, all put in redux, any page state change, through react-redux mapState and mapDispatch to achieve.

The state in redux updates from status to feedback to the view, because the process chain is too long, starting from dispatch an action, and then following logic such as reducer. A complete link contains:

Create action, create redux middleware, create corresponding type reducer functions, create mapState and mapDispatch, etc.

If all states are saved in redux, then each state must go through these steps, which is very tedious, which undoubtedly increases the amount of code.

(2) reduce the unreasonable mixing of local state and redux state.

The complexity of using redux in full is very high. Of course, we consider putting part of the state in redux and part of the state in local state, but in this case, it is easy to create a problem, that is, if local State has a state dependency with the state in redux.

For example, there are 10 students in the status in redux

/ / redux students = [{name: "Xiaobai", score:70}, {name: "Xiao Hong", score:50}....] Copy the code

We keep students with scores above 60 in local state.

/ / local state state = [{name: "Xiaobai", score:70}] copy the code

If the students in redux change, we need to dynamically obtain students information from redux, and then change the local state. With react-redux, we need to use the declaration cycle of componentWillReceivedProps or getDerivedStateFromProps in the container component to change the local local state according to props.

ComponentWillReceivedProps is not discussed here. For higher security, static getDerivedStateFromProps is used instead of componentWillReceivedProps in react. GetDerivedStateFromProps is a declaration periodic function that is executed when both props and state change, so if we need to change the local local state only in the props change, there will be very complex judgment logic in this declaration cycle.

The more states in redux are associated with states in local state, the more complex the declaration cycle function of getDerivedStateFromProps becomes.

The inspiration to us is to reduce the use of getDerivedStateFromProps as much as possible. if redux is related to local state, it is better to use id than to use objects or arrays directly. For example, in the above example, we can group students into groups and give them a group number, which will be changed every time the student information in redux changes. In this way, you only need to determine whether the group number has changed in getDerivedStateFromProps:

Class Container extends React.Component {state = {group_id:number} static getDerivedStateFromProps (props,state) {if (props.grouproomidroomstate.grouproomid) {... Update the passed student} else {return null} copy code

It is recommended that if https://github.com/paularmstrong/normalizr, has a strong relationship between redux and local state, you can first model the data. The normalized data is similar to giving an id to a complex structure, which will simplify the logic of getDerivedStateFromProps.

(3) Summary of this section

How to use redux, we must start from the nature of redux, the essence of redux is to solve the problem of communication between components, so the unique state within components should not be placed in redux. In addition, if redux is used with class components, the data can be modeled and complex judgment logic can be simplified.

II. React hooks manages local state

Now that you've covered how to use redux, how to maintain local state, hooks has been officially added to React16.8. Local state is managed through hooks, which is easy to use and scalable.

There are three common local states in hooks, which are useState, useRef and useReducer.

(1) useState

UseState is the most common local state in hooks, such as:

Const [hide, setHide] = React.useState (false); const [name, setName] = React.useState ('BI'); copy code

To understand useState, it must be clear that in react hooks:

Each rendering has its own Props and State

A classic example is:

Function Counter () {const [count, setCount] = useState (0); function handleAlertClick () {setTimeout () = > {alert ('You clicked on:' + count);}, 3000);} return (

You clicked {count} times

SetCount (count + 1)} > Click me Show alert);} copy the code

If I follow these steps:

Click to add counter to 3

Click "Show alert"

Click to add counter to 5 and finish before the timer callback is triggered

Guess what will happen to alert?

The result is that the pop-up 3 props alert will "capture" my status when I click the button, which means that each rendering will have a separate props and state.

(2) useRef

In react hooks, we know that each rendering will have a separate props and state, so what if we need to get the latest rendering values every time, just like the class components? We can use useRef at this time.

UseRef provides an Mutable variable data

Let's modify the above example so that the alert is 5:

Function Counter () {const [count, setCount] = useState (0) const late = useRef (0) function handleAlertClick () {setTimeout () = > {alert ('You clicked on:' + late.current)}, 3000)} useEffect (() = > {late.current = count}) return (

You clicked {count} times

SetCount (count + 1)} > Click me Show alert)} copy the code

In this way, instead of alert3, 5 pops up after modification.

(3) useReducer

UseReducer is also provided in react hooks to manage local state.

When you want to update one state, and the state update depends on the value of another state, you may need to replace them with useReducer.

The same example is used to illustrate:

Function Counter () {const [state, dispatch] = useReducer (reducer, initialState); const {count, step} = state; useEffect (()) = > {const id = setInterval (() = > {dispatch ({type: 'tick'});}, 1000); return () = > clearInterval (id);}, [dispatch]); return ({count} {dispatch ({type:' step', step: Number (e.target.value)});}} / >) } const initialState = {count: 0, step: 1,}; function reducer (state, action) {const {count, step} = state; if (action.type = 'tick') {return {count: count + step, step};} else if (action.type =' step') {return {count, step: action.step};} else {throw new Error ();}} copy code

To explain the above results, take a look at the useEffect section:

UseEffect (() = > {const id = setInterval (() = > {dispatch ({type: 'tick'});}, 1000); return () = > clearInterval (id);}, [dispatch]); copy code

Count in state depends on step, but after using useReducer, we don't need to use step in useEffect's dependent variation array, but use dispatch instead, which has the advantage of reducing unnecessary rendering behavior.

In addition: useReducer is not recommended for local states, which will cause the internal state of the function to be too complex to read. UseReducer recommends that you use it in conjunction with useContext when communicating between multiple components.

3. How to solve the communication between components by react hooks

Local state management in react hooks is more brief than class components, so if our components use react hooks, then how to solve the problem of communication between components.

# (1) UseContext

Perhaps the most basic idea is to solve the problem of communication between components through useContext.

For example:

Function useCounter () {let [count, setCount] = useState (0) let decrement = () = > setCount (count-1) let increment = () = > setCount (count + 1) return {count, decrement, increment}} let Counter = createContext (null) function CounterDisplay () {let counter = useContext (Counter) return

You clicked {counter.count} times

+)} function App () {let counter = useCounter () return ()} copy the code

In this example, through createContext and useContext, you can use context in CounterDisplay, a subcomponent of App, to achieve component communication in a certain sense.

In addition, on the basis of useContext, for the sake of integrity, the industry also has several relatively simple packages:

Github.com/jamiebuilds... Github.com/diegohaz/co...

But its essence does not solve a problem:

If there are too many context, how to maintain these context

In other words, in the scenario of a large number of component communication, the readability of the component communication code using context is very poor. The scenario of this class component is consistent, and context is not a new thing, although the use of useContext reduces the complexity of using context.

# (2) Redux combines hooks to realize the communication between components

Communication between hooks components can also be achieved using redux. In other words:

In React hooks, redux also has its existence meaning.

There is a problem in hooks because there is no high-level component like connect in react-redux to pass mapState and mapDispatch, and the solution is to use redux-react-hook or the 7.1 hooks version of react-redux.

Redux-react-hook

StoreContext, useDispatch and useMappedState are provided in redux-react-hook to operate store in redux. For example, mapState and mapDispatch are defined as follows:

Import {StoreContext} from 'redux-react-hook';ReactDOM.render (, document.getElementById (' root'),); import {useDispatch, useMappedState} from 'redux-react-hook';export function DeleteButton ({index}) {/ / Declare your memoized mapState function const mapState = useCallback (state = > ({canDelete: state.todos.canDelete, name: state.todos.name,}), [index],); / / Get data from and subscribe to the store const {canDelete, name} = useMappedState (mapState) / / Create actions const dispatch = useDispatch (); const deleteTodo = useCallback (() = > dispatch ({type: 'delete todo', index,}), [index],); return (Delete {name});} copy code

Hooks version of react-redux 7.1

This is also officially recommended. The hooks version of react-redux provides three main methods: useSelector (), useDispatch () and useStore (), corresponding to mapState, mapDispatch and store instances directly obtained from redux.

A brief introduction to useSelector, in addition to getting state from store, useSelector also supports the function of depth comparison. If the corresponding state is not changed, it will not be recalculated.

For example, the most basic usage:

Import React from 'react'import {useSelector} from' react-redux'export const TodoListItem = props = > {const todo = useSelector (state = > state.todos [props.id]) return {todo.text} copy the code

Usage to implement caching:

Import React from 'react'import {useSelector} from' react-redux'import {createSelector} from 'reselect'const selectNumOfDoneTodos = createSelector (state = > state.todos, todos = > todos.filter (todo = > todo.isDone) .length) export const DoneTodosCounter = () = > {const NumOfDoneTodos = useSelector (selectNumOfDoneTodos) return {NumOfDoneTodos} export const App = () = > {return (Number of done todos:)} copy code

In the above cache usage, as long as todos.filter (todo = > todo.isDone) .length does not change, it will not be recalculated.

IV. Summary

The complete state management in react is divided into global state and local state, while react hooks simplifies the local state, making it extremely convenient to manage local state and control local rendering, but react hooks is essentially a view component layer, and does not perfectly solve the problem of communication between components, that is to say, state management machines such as redux and react hooks are not contradictory in nature.

In my practice, redux is used to realize the communication between components and react hooks to achieve local state management, which not only makes the code easy to read, but also reduces a lot of unnecessary redux boilerplate code.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report