TodoList operations are implemented using redux and React-Redux respectively.

useuseContext.useReducer.createContextIn place of the Redux counter case

1. Install

npm install redux react-redux --save
Copy the code

2. Files in the store folder.

  • Action.js(provides functions for each action object),
  • ActionTypes.js(Action type constant),
  • index.js(Provides access to data),
  • Reducer.js(Operation on data)

// Action.js

    import { ADDITEM, DELETEITEM } from './ActionTypes'
    // Add action
    export const addHandle = () = > {
      return {
        type: ADDITEM
      }
    }
    // Delete action
    export const deleteHandle = () = > {
      return {
        type: DELETEITEM
      }
    }

Copy the code
// ActionTypes.js

    export const ADDITEM = "addItem"
    export const DELETEITEM = "deleteItem"
Copy the code
// index.js

    import { createStore } from "redux";
    import reducer from './Reducer'

// Parameter 2 indicates that the redux-tools plug-in is used
    const store = createStore(
    reducer, 
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );

    export default store;
Copy the code
// reducer.js
    
    import { ADDITEM, DELETEITEM } from './ActionTypes'

    let defaultState = {
      defaultValue: "I'm the default.".list: [
        "What a beautiful day!"."It was fine yesterday."]}export default function reducer(state = defaultState, action) {
      if (action.type === ADDITEM) {
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.push(action.value)
        return newState
      }
      if (action.type === DELETEITEM) {
        let newState = JSON.parse(JSON.stringify(state))
        newState.list.splice(action.index, 1)
        return newState
      }
      return state
    }
Copy the code

3. Use redux

    import React, { Component, createRef } from 'react';
    import store from './store';
    import { addHandle, deleteHandle } from './store/Action'
    
    export default class TestRedux extends Component {
      constructor(props) {
        super(props)
        // this.state cannot be equal to non-object values
        this.state = store.getState();
        this.inputDom = createRef();
      }
      componentDidMount() {
        store.subscribe(() = > this.setState(store.getState()))
      }
      / / add
      addItem = () = > {
        if (this.inputDom.current) { store.dispatch({ ... addHandle(),value: this.inputDom.current.value })
        }
      }
      / / delete
      deleteItem = (index) = > {
        console.log(index) store.dispatch({ ... deleteHandle(), index }) }render() {
        return <div>
          <input type="text" ref={this.inputDom} placeholder={this.state.defaultValue} />
          <button onClick={this.addItem}>increase</button>
          <ul>
            {
              this.state.list && this.state.list.map((item, index) => <li onClick={()= > this.deleteItem(index)} key={index}>{item}</li>)}</ul>
        </div>}}Copy the code

4. Use the React-Redux built-in component Provider package that requires components that use store data

Components wrapped through the Provider component (which provides stores) can access values in stores.

// App.js

    import TestRedux from './TestRedux';
    import { Provider } from 'react-redux'
    import store from "./store";
    
    <Provider store={store}>
      <TestRedux></TestRedux>
    </Provider>
Copy the code

5. Use the react-Redux built-in function connect to wrap components that use store data

A component that uses store is wrapped with CONNECT (stateToProps, dispatchToProps)(component), which passes a state mapping function and a Dispatch mapping function. All mapped to props.

Note: If the Dispatch operation needs to access the data in the component, we can pass parameters through events.

// TestRedux.jsx
    import React, { createRef } from 'react';
    import { connect } from 'react-redux';
    import { addHandle, deleteHandle } from './store/Action'

     const TestRedux = (props) = > {
       const inputDom = createRef();
       const { list, defaultValue, addItem, deleteItem } = props
       return (<div>
         <input type="text" ref={inputDom} placeholder={defaultValue} />
         <button onClick={()= >AddItem (inputDom)} ></button>
         <ul>
           {
             list && list.map((item, index) => <li onClick={()= > deleteItem(index)} key=  {index}>{item}</li>)}</ul>
       </div>)}// Map the values in store to props.
    const stateToProps = (state) = > {
      return {
        defaultValue: state.defaultValue,
        list: state.list
      }
    }
    // Map the event to props
    const dispatchToProps = (dispatch) = > {
      return {
        / / add
        // If we need to get a specific value in the component, for example: dom. We can pass parameters through events.
        addItem(inputDom) {
          if(inputDom.current) { dispatch({ ... addHandle(),value: inputDom.current.value })
          }
        },
        / / delete
        deleteItem(index){ dispatch({ ... deleteHandle(), index }) } } }export default connect(stateToProps, dispatchToProps)(TestRedux)
Copy the code

6. Use useContext and useReducer instead of redux

We used createContext() in the parent component to provide state and dispatch, and useReducer(Reducer, initState) to do data processing

throughuseContext()In order to getProviderComponent-wrapped components use state and dispatch values to perform operations.

JSX ----- parent component

    import React, { createContext, useReducer } from "react";

    export const countContext = createContext({});
    export const UPCOUNT = "UPCOUNT"
    export const DOWNCOUNT = "DOWNCOUNT"

    function reducer(state, action) {
      switch (action.type) {
        case UPCOUNT:
          return action.value;
        case DOWNCOUNT:
          return action.value
        default:
          returnstate; }}export default function UpDown(props) {
      const [count, dispatch] = useReducer(reducer, 0)
      return (
      // Note that value is passed as an object
        <countContext.Provider value={{ count.dispatch}} >
          {props.children}
        </countContext.Provider>)}Copy the code
// operator.js ---- child component

    import { useContext } from "react";
    import { DOWNCOUNT, countContext, UPCOUNT } from './UpDown'

    export default function Operator(props) {
      const { count, dispatch } = useContext(countContext);

      return (
        <div>
          <p>Current count: {count}</p>
          <button onClick={()= >Dispatch ({type: UPCOUNT, value: count + 1})}> Add</button>
          <button onClick={()= >Dispatch ({type: DOWNCOUNT, value: count-1})}> Reduce</button>
        </div>)}Copy the code