As we all know, data communication in React is one-way. That is, the parent component can pass data to the child component through props, but the child component cannot pass data to the parent. The need for a child component to pass data to its parent requires the parent component to provide a way to modify the data, and as the number of pages increases, data management becomes extremely complex. Also, setState needs to be called every time data is updated, which can be particularly troublesome when it comes to cross-component communication. In React development, a large number of state management frameworks have been developed to solve the problem of cross-component communication. Currently, Flux, Redux, Mobx and other commonly used React state management frameworks are several. Among them, Flux is the front-end architecture used by Facebook to build client Web applications. It supplements the composite view component of React with a one-way data flow, which solves the problem of chaotic data flow management in MVC technical architecture. Redux is an open source front-end state management framework developed by Dan Abramov. Redux framework consists of Action, Store and Reducers. Data of all components are stored in Store objects, and each component only needs to change the data in Store. When Store data changes, other subscribed components perform data updates. Mobx is an object-oriented state management framework that differs from Redux in that the data can be modified directly and the UI can be accurately notified to refresh rather than broadcast by Redux. You can find that Redux is particularly suited for scenarios that require centralized management of data. Multiple components use the same data source and maintain the same data sample, thus maintaining data consistency between components. React-redux is a technical implementation of redux state management framework in React. For developers familiar with redux state management framework, learning React-Redux should be very easy. In the framework of Redux state, Redux divides state management into Action, Store and Reducers. Redux stores the state of the application into the Store, the component triggers the Action through dispatch(), and the Store receives the Action and forwards it to the Reducer. Reducer processes the state data according to the Action type and returns the processing results to the Store. Other components refresh their state by subscribing to the Store state. Figure 3-9 shows the work flow of the whole framework.

The following uses counters as an example to illustrate the basic use of Redux. First, create an action.js file to hold the action action events, as shown below.

export const ADD = 'ADD'
export const MINUS = 'MINUS'
Copy the code

Then create a reducer. Js file that handles the business logic updates and returns the results to the Store, as shown below.

import {ADD, MINUS} from './action';

function reducer (state = {count: 0}, action) {
    switch(action.type) {
        case ADD:
            return {count: state.count + 1}
        case MINUS:
            return {count: state.count - 1}
        default:
            return state
    }
}
export default reducer;
Copy the code

Reducer is a pure function that accepts State and Action. State is the old State and cannot be directly modified. Reducer will generate different new states according to Action types and return the results to the Store. Next, create a global Store object to Store the application’s state data using the store-provided createStore() method, as shown below.

import { createStore } from 'redux'
import reducer from './reducer';
const store = createStore(reducer)
export default store
Copy the code

In addition to the createStore() method, the created Store has several other methods that can be called.

  • GetState () : Gets the latest status data.
  • Dispatch () : dispatches Action Action events.
  • Subscribe () : State changes in the subscription Store.

To implement counter addition and subtraction, you also need to add a subscription event to the component’s lifecycle function and resolve the subscription when the component is destroyed, as shown below.

class CounterPage extends React.Component {

    constructor(props){
        super(props)
        this.state = {
            number: store.getState().count
        }
    }

    componentDidMount () {
        this.unSubscribe = store.subscribe(() = > {this.setState({
                number: store.getState().count
            })
        })
    }

    componentWillUnmount () {
        this.unSubscribe && this.unSubscribe()}render() {
        return (
            <View style={styles.ct}>
                <Text>{this.state.number}</Text>
                <Button
                    title="+ 1"
                    onPress={() => store.dispatch({type: 'ADD'})}/>
                <Button
                    title="1"
                    onPress={() => store.dispatch({type: 'MINUS'})}/> </View> ); }}const styles = StyleSheet.create({
    ct: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',}});export default CounterPage;
Copy the code

In the above code, we get the latest State using the store.getState() method, and dispatch the Action to the store using the store.dispatch() method when we perform the addition and subtraction operation. Using Redux in a class component is cumbersome and requires the developer to manage the component’s state data. Using React Hook is much simpler. To use Redux in React Hook, use the useSelector() and useDispatch() functions provided by the React-Redux library. The useSelector() function can be used to get state values, while useDispatch() can be used to modify state data, as shown below.

import { useSelector, useDispatch } from 'react-redux'

const CounterPage = () => {
    
    const count = useSelector(state => state.count)
    const dispatch = useDispatch(a)return (
        <View style={styles.ct}>
            <Text>{count}</Text>
            <Button
                title='1'
                onPress={() => dispatch({type: 'ADD'})}/>
            <Button
                title='1'
                onPress={() => dispatch({type: 'MINUS'})}/>
        </View>
    );
}

const styles = StyleSheet.create({... .// omit the code
});

export default CounterPage
Copy the code

As you can see, the React Hook implementation is much cleaner than the class component. First, we use the useSelector() function to get the state in the Store, and then use the useDispatch() function to dispatch events. Finally, when using Redux to share state data between different components, you also need to wrap application components with the Provider provided by the React-Redux library, as shown below.

const App = () => {
    return (
        <Provider store={store}>
            <CounterPage />
        </Provider>
    );
};
Copy the code

Rerunning the code completes the function of the counter, as shown below.

Finally, the following points should be noted when using Redux for state management: • There is only one Store in an application that stores the state of the entire application. • State is read-only and can only be modified by sending Action events. To describe the process of Action changing State, use the Reducer pure function. • A single data source facilitates communication between React components and provides unified state management.