In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)05/31 Report--
Most people do not understand the knowledge points of this "React State Mode case Analysis" article, so the editor summarizes the following content, detailed content, clear steps, and has a certain reference value. I hope you can get something after reading this article. Let's take a look at this "React State Mode case Analysis" article.
Understand state in React
In its purest form, React can be thought of as a blueprint. Given some state, your application will appear in some way. React prefers declarative to imperative, which is a fancy way of saying that you write down what you want to happen rather than the steps to achieve it. Because of this, it is extremely important to manage state correctly, because state controls how your application behaves.
State in action
Before we begin, it would be helpful to briefly discuss what the state is. Personally, I think that a state is a collection of variable values that changes over time and directly affects the behavior of the component.
The state is very similar to prop, except that the state can be changed in its defined context, while the received prop cannot be changed without a callback function.
Let's take a look:
Const UserList = () = > {const [users, setUsers] = useState ([]) useEffect () = > {const getUsers = async () = > {const response = await fetch ("https://myuserapi.com/users") const users = await response.json () setUsers (users)} getUsers ()}, []) if (users.length)
< 1) return null; return {users.map(user =>{user.name})}}
In this example, we get the users from the API when the component is installed, and update the array of users after receiving the response. We naively assume that the call is always successful to reduce the complexity of this example.
We can see that the state is used to render a list item with a user name, and if there are no users in the array, it will return empty. The state changes over time and is used to directly affect the behavior of the component.
Another thing worth noting here is that we are using React's built-in state management method, using useState Hook. Depending on the complexity of your application and state management, you may only need to use React's built-in Hook to manage your state.
However, from a large number of state management solutions in React, it can be seen that the built-in state management methods are sometimes not enough. Let's look at some of the reasons.
Learn about prop
Let's consider a slightly more complex application. As your application grows, you have to create multiple layers of components to separate concerns and / or improve readability. The problem arises when you have the required state of multiple components, which have different locations on the tree.
If we want to provide user data to UserMenu and Profile components, we have to put the state in App, because this is the only place where we can propagate the data to every component that needs it.
This means that we will contaminate unnecessary data to them through components that may not need it, such as dashboards and settings.
Now, what if you need to manipulate the data in another component? Then, you need to provide the update function (the setUsers function in the previous example) to the component that needs to be updated, and add another property that needs to be propagated down-all for a state. Now imagine adding five more attributes to make it more complicated. It will soon get out of control.
To me, this means how comfortable I am about updating machine functions through multiple layers of components. Personally, I have a hard limit on the three layers; after that, I will find another solution. But until then, I insisted on using the built-in features of React.
State libraries also have costs, and there is no reason to add unnecessary complexity unless you are sure you absolutely need them.
The problem of re-rendering
Because React automatically triggers re-rendering after a status update, once the application grows, there will be problems with internal state processing. Different branches of the component tree may require the same data, and the only way to provide the same data for these components is to promote the state to the nearest common ancestor.
As the application grows, a large number of states will need to move up the component tree, which will increase the complexity of the prop and cause unnecessary resubmit when the status is updated.
Test question
Another problem with saving all states in components is that your state processing becomes cumbersome. Stateful components require you to set up complex test scenarios where you invoke actions that trigger the state and match the results. Testing state in this way quickly becomes complex, and changing the way state works in your application often requires a complete rewrite of your component tests.
Manage state with Redux
As far as state libraries are concerned, one of the most prominent and widely used libraries for managing states is Redux. Launched in 2015, Redux is a state container that helps you write maintainable and testable states. It is based on the principles of Flux, and Flux is an open source architecture model of Facebook.
In essence, Redux provides a global state object that provides each component with the state it needs, and only re-renders the components (and their subcomponents) that receive that state. Redux manages statements based on actions and restores. Let's take a quick look at these components.
In this example, the component dispatches an action that is sent to the reducer. Reducer updates the status, which in turn triggers a re-rendering.
State
State is the only source of truth; it represents your state at all times. Its job is to provide state for the component. Example:
{users: [{id: "1231", username: "Dale"}, {id: "1235", username: "Sarah"}]}
Actions
Actions are predefined objects that represent changes in state. They are plain text objects that follow some kind of contract.
{type: "ADD_USER", payload: {user: {id: "5123", username: "Kyle"}
Reducers
Reducer is a function that receives actions and is responsible for updating state objects.
Const userReducer = (state, action) = > {switch (action.type) {case "ADD_USER": return {... state, users: [... state.users, action.payload.user]} default: return state;}} Modern React State Mode
Although Redux is still a great tool, over time, React has developed and given us new technologies. In addition, new ideas and ideas have also been introduced into state management, resulting in many different ways to deal with states. Let's look at some more contemporary patterns in this section.
UseReducer and Context API
React 16.8 introduces Hooks, which provides us with a new way to share functionality through applications. Therefore, we can now use React's built-in Hook called useReducer, which allows us to create Reducer out of the box. If we match this feature to React's Context API, we now have a lightweight solution similar to Redux that we can use through our application.
Let's look at an example of a reducer that handles API calls:
Const apiReducer = (state = {}, action) = > {switch (action.type) {case "START_FETCH_USERS": return {... state, users: {success: false, loading: true, error: false, data: []}} case "FETCH_USERS_SUCCESS": return {... state Users: {success: true, loading: true, error: false, data: action.payload.data}} case "FETCH_USERS_ERROR": return {... state, users: {success: false, loading: false, error: true, data: []} case default: return state}}
Now that we have our Reducer, let's create our context:
Const apiContext = createContext ({}) export default apiContext
With these two pieces, we can now combine them to create a highly flexible state management system:
Import apiReducer from'. / apiReducer' import ApiContext from'. / ApiContext const initialState = {users: {success: false, loading: false, error: false, data: []} const ApiProvider = ({children}) = > {const [state, dispatch] = useReducer (apiReducer, initialState) return {children}}
With this done, we now need to wrap the provider around the components in our application that need to access this state. For example, at the root of our application:
ReactDOM.render (document.getElementById ("root"),)
Now, any component that is the child of App will be able to access the status and scheduler of our ApiProviders in order to trigger action and access the state as follows:
Import React, {useEffect} from 'react' import ApiContext from'.. / ApiProvider/ApiContext const UserList = () = > {const {users ApiDispatcher} = useContext (ApiContext) useEffect (() = > {const fetchUsers = () = > {apiDispatcher ({type: "START_FETCH_USERS"}) fetch ("https://myapi.com/users") .then (res = > res.json ()) .then (data = > apiDispatcher ({type:" FETCH_USERS_SUCCCESS ") Users: data.users}) .catch ((err) = > apiDispatcher ({type: "START_FETCH_ERROR"}))} fetchUsers ()}, [])
Use state machine and XState to manage state
Another popular way to manage state is to use a state machine. In short, a state machine is a dedicated state container that can hold a limited number of states at any time. This makes the state machine highly predictable.
Since each state machine follows the same pattern, you can insert a state machine in the generator and receive a state diagram with an overview of the data flow.
State machines generally follow stricter rules than Redux in terms of format to maintain predictability.
In the world of React state management, XState is the most popular library for creating, interpreting, and processing state machines.
Let's take a look at the example in the XState document:
Import {createMachine, interpret, assign} from 'xstate' Const fetchMachine = createMachine ({id: 'Dog API', initial:' idle', context: {dog: null}, states: {idle: {on: {FETCH: 'loading'}}, loading: {invoke: {id:' fetchDog', src: (context) Event) = > fetch ('https://dog.ceo/api/breeds/image/random').then((data) = > data.json ()), onDone: {target:' resolved', actions: assign ({dog: (_, event) = > event.data})}, onError: 'rejected'} On: {CANCEL: 'idle'}}, resolved: {type:' final'}, rejected: {on: {FETCH: 'loading'}) Const dogService = interpret (fetchMachine) .ontransition ((state) = > console.log (state.value)) .start (); dogService.send ('FETCH')
UseSWR
Over the years, state management has become more and more complex. While proper state management plus a view library like React allows us to do some amazing things, there is no doubt that we are moving a lot of complexity to the front end. As complexity increases, we also incur more cognitive load, more indirectness, more potential errors, and more code that needs to be thoroughly tested.
In this respect, useSWR is a breath of fresh air. Matching this library to React Hooks's native features creates a degree of simplicity that is hard not to like. The library uses HTTP caching technology stale-while-revalidate, which means that it retains the local cache of the previous dataset and synchronizes with API in the background to get fresh data.
This keeps the application highly performance and user-friendly because the user interface can respond with stale dates while waiting for updates. Let's take a look at how we can use this library to get rid of some complex state management:
/ / Data fetching hook import useSWR from 'swr' const useUser (userId) {const fetcher = (... args) = > fetch (.args). Then (res = > res.json () const {data, error} = useSWR (`/ api/user/$ {userId}`, fetcher) return {user: data, error, loading:! data & &! error}} export default useUser
Now that we have a reusable Hook, we can use it to enter data into our component view. You don't need to create restores, actions, or connect components to state in order to get data-- just import and use Hook in components that need data:
Import Loader from'.. / components/Loader' import UserError from'.. / components/UserError' import useUser from'.. / hooks/useUser'; const UserProfile = ({id}) = > {const {user, error, loading} = useUser (id); if (loading) return if (error) return return {user.name}.}
Another component:
Import Loader from'.. / components/Loader' import UserError from'.. / components/UserError' import useUser from'.. / hooks/useUser'; const Header = ({id}) = > {const {user, error, loading} = useUser (id); if (loading) return if (error) return return.}
This method allows you to easily pass Hooks that can access the shared data object, because the first parameter of useSWR is a Key.
Const {data, error} = useSWR (`/ api/user/$ {userId}`, fetcher)
Based on this Key, our requests are compressed, cached, and shared among all our components that use useUser Hook.
This also means that only one request is sent to API as long as the key matches. Even if we have 10 components that use useUser Hook, only one request is sent as long as the useSWR key matches.
The above is about the content of this article "case Analysis of React State Mode". I believe we all have a certain understanding. I hope the content shared by the editor will be helpful to you. If you want to know more related knowledge, please pay attention to the industry information channel.
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.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.