redux、react-redux、useReducer、useContext

简介: redux、react-redux、useReducer、useContext

分别使用reduxreact-redux来实现todoList操作。


使用useContext, useReducer, createContext来代替redux, 计数器案例


1. 安装


npm install redux react-redux --save


2. store文件夹下文件。


  • Action.js(提供各个action对象的函数),


  • ActionTypes.js(action中type常量),


  • index.js(提供访问数据),


  • Reducer.js(对数据的操作)


网络异常,图片无法展示
|


// Action.js
    import { ADDITEM, DELETEITEM } from './ActionTypes'
    // 增加的action
    export const addHandle = () => {
      return {
        type: ADDITEM
      }
    }
    // 删除的action
    export const deleteHandle = () => {
      return {
        type: DELETEITEM
      }
    }


// ActionTypes.js
    export const ADDITEM = "addItem"
    export const DELETEITEM = "deleteItem"


// index.js
    import { createStore } from "redux";
    import reducer from './Reducer'
// 参数二,表示使用redux-tools插件
    const store = createStore(
    reducer, 
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    );
    export default store;


// reducer.js
    import { ADDITEM, DELETEITEM } from './ActionTypes'
    let defaultState = {
      defaultValue: "我是默认值",
      list: [
        "今天天气真好啊",
        "昨天天气也好啊"
      ]
    }
    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
    }


3. 使用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不能等于非Object的值
        this.state = store.getState();
        this.inputDom = createRef();
      }
      componentDidMount() {
        store.subscribe(() => this.setState(store.getState()))
      }
      // 增加
      addItem = () => {
        if (this.inputDom.current) {
          store.dispatch({ ...addHandle(), value: this.inputDom.current.value })
        }
      }
      // 删除
      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}>增加</button>
          <ul>
            {
              this.state.list && this.state.list.map((item, index) => <li onClick={() => this.deleteItem(index)} key={index}>{item}</li>)
            }
          </ul>
        </div>
      }
    }


4. 使用react-redux的内置组件Provider包裹需要使用store中数据的组件


通过Provider组件(提供store)包裹的组件,都可以访问store中的值。


// App.js
    import TestRedux from './TestRedux';
    import { Provider } from 'react-redux'
    import store from "./store";
    <Provider store={store}>
      <TestRedux></TestRedux>
    </Provider>


5. 使用react-redux的内置函数connect包裹需要使用store中数据的组件


使用connect(stateToProps, dispatchToProps)(组件)包裹使用store的组件,该函数传递一个state映射函数和dispatch映射函数。都被映射到props上。


注意: 如果dispatch操作需要访问组件中的数据,我们可以通过事件传递参数。


// 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>)
     }
    // 将store中得值映射到props上。
    const stateToProps = (state) => {
      return {
        defaultValue: state.defaultValue,
        list: state.list
      }
    }
    // 将事件映射到props上
    const dispatchToProps = (dispatch) => {
      return {
        // 增加
        // 如果我们需要在组件中获取到特定的值,例如:dom。我们可以通过事件传递参数。
        addItem(inputDom) {
          if (inputDom.current) {
            dispatch({ ...addHandle(), value: inputDom.current.value })
          }
        },
        // 删除
        deleteItem(index) {
          dispatch({ ...deleteHandle(), index })
        }
      }
    }
export default connect(stateToProps, dispatchToProps)(TestRedux)


6. 使用useContext和useReducer来代替redux


我们在父组件中使用createContext()来提供state和dispatch,使用useReducer(reducer, initState)来做数据处理操作


通过useContext()来获取Provider组件包裹的组件中使用state,dispatch值做出一些操作。


// UpDown.jsx-----父组件
    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:
          return state;
      }
    }
    export default function UpDown(props) {
      const [count, dispatch] = useReducer(reducer, 0)
      return (
      // 注意:这里的value传递的是对象
        <countContext.Provider value={{ count, dispatch }}>
          {props.children}
        </countContext.Provider>
      )
    }
// Operator.js ----子组件
    import { useContext } from "react";
    import { DOWNCOUNT, countContext, UPCOUNT } from './UpDown'
    export default function Operator(props) {
      const { count, dispatch } = useContext(countContext);
      return (
        <div>
          <p>当前计数:{count}</p>
          <button onClick={() => dispatch({ type: UPCOUNT, value: count + 1 })}>增加</button>
          <button onClick={() => dispatch({ type: DOWNCOUNT, value: count - 1 })}>减少</button>
        </div>
      )
    }


相关文章
|
3天前
|
存储 JavaScript 前端开发
掌握现代Web开发的基石:深入理解React与Redux
【10月更文挑战第14天】掌握现代Web开发的基石:深入理解React与Redux
10 0
|
2天前
|
存储 JavaScript 前端开发
React中使用redux
【10月更文挑战第15天】
11 3
|
2月前
|
前端开发
react中 useContext 和useReducer的使用
react中 useContext 和useReducer的使用
react中 useContext 和useReducer的使用
|
13天前
|
存储 JavaScript 前端开发
如何使用React和Redux构建现代化Web应用程序
【10月更文挑战第4天】如何使用React和Redux构建现代化Web应用程序
|
14天前
|
JavaScript 前端开发
使用 React 和 Redux 构建动态图表应用
【10月更文挑战第3天】使用 React 和 Redux 构建动态图表应用
|
14天前
|
JavaScript 前端开发
使用 React 和 Redux 构建一个计数器应用
【10月更文挑战第3天】使用 React 和 Redux 构建一个计数器应用
|
16天前
|
存储 JavaScript 前端开发
|
16天前
|
前端开发 JavaScript 网络架构
实现动态路由与状态管理的SPA——使用React Router与Redux
【10月更文挑战第1天】实现动态路由与状态管理的SPA——使用React Router与Redux
26 1
|
2月前
|
存储 JavaScript 前端开发
React中使用redux
React中使用redux
131 56
|
10天前
|
前端开发 JavaScript
深入理解前端状态管理:React、Redux 和 MobX
【10月更文挑战第7天】深入理解前端状态管理:React、Redux 和 MobX
10 0