• ReactRedux


    React-Redux

    • React-Redux 是 Redux 的官方 React 绑定库。
    • React-Redux 能够使React组件从Redux store中读取数据,并且向 store 分发 actions 以更新数据。
    • React-Redux 并不是 Redux 内置,需要单独安装。
    • React-Redux 一般会和 Redux 结合一起使用。

    一、安装redux、react-redux

                npm  install  redux

                npm    install   react-redux

    二、Provider 和 connect

    Provider:它是react-redux 提供的一个 React 组件,作用是state传给它的所有子组件,也就是说 当你用Provider传入数据后 ,下面的所有子组件都可以共享数据,十分的方便。
         Provider的使用方法是:Provider组件包裹在最外层的组件

            <Provider  store={ store }>

                <App />

            </Provider>

    注意:一定是在Provider中传store

    connect:它是一个高阶组件 所谓高阶组件就是给它传入一个组件,它会返回新的加工后的组件,connect 方法有四个参数([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])后面两个参数可以不写,不写的话它是有默认值的。主要关注前两个参数: mapStateToProps mapDispatchToProps;

    Ø mapStateToProps如果定义该参数,组件将会监听 Redux store 的变化。任何时候,只要 Redux store 发生改变,mapStateToProps 函数就会被调用。

    Ø mapDispatchToProps如果传递的是一个对象,那么每个定义在该对象的函数都将被当作 Redux action creator,对象所定义的方法名将作为属性名;每个方法将返回一个新的函数,函数中dispatch方法会将 actioncreator 的返回值作为参数执行。这些属性会被合并到组件的 props 中。

    connect的使用方法是:把指定的state和指定的action与React组件连接起来,后面括号里面写UI组件名

      connect(mapStateToProps,mapDispatchToProps)(TbItem)

    三、示例:

    1:利用react-redux实现计数器

    1目录结构

         

     2store.js

    import {createStore} from "redux";
    export const ADD = 'ADD';
    export const MINUS = 'MINUS';

    function reducer (state= {count:0},action){
        console.log('Action:',action);
        switch (action.type) {
            case ADD:
                return { count: state.count + 1}
            case MINUS:
                return { count: state.count - 1}
            default:
                return state
        }
    }
    let store = createStore(reducer);
    export default store;

    3action.js

    function add() {
        return {
            type: 'ADD'
        }
    }

    function minus() {
        return {
            type: 'MINUS'
        }
    }

    const action = { add,minus }

    export default action;

     

    4Counter1.js

    import React,{ Component } from "react";
    import { connect } from "react-redux";
    import action from "../actions/action";

    class Counter1 extends Component {
        render() {
            return (
                <div>
                    <p>{ this.props.count }</p>
                    <button onClick={this.props.add }>Count++</button>
                       
                    <button onClick={ this.props.minus}>count--</button>
                </div>
            )
        }
    }
    const mapStateToProps = state=> state

    const mapDispatchToProps = {
        ...action
    }

    export default connect(mapStateToProps,mapDispatchToProps)(Counter1);

     

    5App.js

    import logo from './logo.svg';
    import './App.css';
    import Counter1 from "./components/Counter1";
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <Counter1 />
          </header>
        </div>
      );
    }

    export default App;

     

    6index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { Provider } from "react-redux";
    import store from "./store/store";

    ReactDOM.render(
      <Provider  store={ store }>
        <App />
      </Provider>,
      document.getElementById('root')
    );

     

      action:行为 它是一个对象 里面必有type来指定其类型 这个类型可以理解为你要做什么,reducer要根据action的type来返回不同的state 每个项目有且可以有多个action。它是 store 数据的唯一来源。通过 store.dispatch() 将 action 传到 store。记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。

    reducer: 可以理解为一个专门处理state的工厂,给它一个旧数据它会根据不同action.type返回新的数据,每个项目有且可以有多个reducer。reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的。

    store: store本质上是一个状态树,保存了所有对象的状态。任何UI组件都能直接的从store访问特定对象的状态。每个项目有且只能有一个store。

    • 提供 getState() 方法获取 state;
    • 提供 dispatch(action) 方法更新 state;
    • 通过 subscribe(listener) 注册监听器;

     

      

    2:多组件共享store

              

    (1)constants.js定义公共方法名

    export const ADD_NUMBER = 'ADD_NUMBER'
    export const SUB_NUMBER = 'SUB_NUMBER'

     

    (2)actionCreators.js(专门存放方法名)

    import {
        ADD_NUMBER,
        SUB_NUMBER
    } from "./constants";

    export const addAction = num => ({
        type: ADD_NUMBER,
        num
    })

    export const subAction = num => ({
        type: SUB_NUMBER,
        num
    })

       (3)reducer.js(存放事件)

    import {
        ADD_NUMBER,
        SUB_NUMBER
    } from "../action/constants";

    const deflateState = {
        counter: 0
    }

    function reducer(state = deflateState,action){
        switch (action.type){
            case ADD_NUMBER:
                return {...state,counter: state.counter + action.num }
            case SUB_NUMBER:
                return {...state,counter: state.counter - action.num }
            default:
                return state;
        }
    }
    export default reducer;

       (4)store.js文件

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

    const store = createStore(reducer);

    export default store;

       (5)home.js(Home组件)

    import React,{ Component } from "react";
    import store from "../redux/store/store";
    import { addAction } from "../redux/action/actionCreators";

    export default class Home extends Component {
        constructor(props) {
            super(props);
            this.state = {
                counter: store.getState().counter
            }
        }
        //订阅
        componentDidMount() {
            this.unSubscribe = store.subscribe(()=>{
                this.setState({
                    counter: store.getState().counter
                })
            })
        }
        //取消订阅
        componentWillUnmount() {
            this.unSubscribe();
        }
        render() {
            return (
                <div>
                    <h2>Home</h2>
                    <h3>当前: { this.state.counter }</h3>
                    <button onClick={ event => this.increment() }>+1</button>
                    <button onClick={ event => this.addNumber(5) }>+5</button>
                </div>
            )
        }

        increment(){
            store.dispatch(addAction(1));
        }

        addNumber(num){
            store.dispatch(addAction(num));
        }
    }

    7about.js(About组件)

    import React,{ Component } from "react";
    import store from "../redux/store/store";
    import { addAction } from "../redux/action/actionCreators";

    export default class Home extends Component {
        constructor(props) {
            super(props);
            this.state = {
                counter: store.getState().counter
            }
        }
        //订阅
        componentDidMount() {
            this.unSubscribe = store.subscribe(()=>{
                this.setState({
                    counter: store.getState().counter
                })
            })
        }
        //取消订阅
        componentWillUnmount() {
            this.unSubscribe();
        }
        render() {
            return (
                <div>
                    <h2>Home</h2>
                    <h3>当前: { this.state.counter }</h3>
                    <button onClick={ event => this.increment() }>+1</button>
                    <button onClick={ event => this.addNumber(5) }>+5</button>
                </div>
            )
        }

        increment(){
            store.dispatch(addAction(1));
        }

        addNumber(num){
            store.dispatch(addAction(num));
        }
    }

    (8)App.js

    import logo from './logo.svg';
    import './App.css';
    import Home from "./components/home";
    import About from "./components/about";
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <Home />
            <About/>
          </header>
        </div>
      );
    }

    export default App;

     (9)index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import store from "./redux/store/store";
    import { Provider } from "react-redux";

    ReactDOM.render(
      <Provider store={store}>
          <App />
      </Provider>,
      document.getElementById('root')
    );

     

    3、合并多个reducer

         (1)目录结构

            

       (2)action文件

           2.1、changeAge_action.js

    export const CLICK_ADD = 'CLICK_ADD';
    export const CLICK_SUB = 'CLICK_SUB';

    export function clickAdd() {
        return {
            type: CLICK_ADD
        }
    }
    export function clickSub() {
        return {
            type: CLICK_SUB
        }
    }

           2.2、inputInfo.js

    export const INPUT_INFO = 'INPUT_INFO';

    export function inputInfo(name){
        return {
            type: INPUT_INFO,
            name
        }
    }

    (3)reducer文件

       3.1、changeAge_reducer.js

    import { CLICK_ADD,CLICK_SUB } from "../actions/changeAge_action";

    function initialState() {
        return {
            age: 20
        };
    }

    function changeAge(state=initialState(),action) {
        switch (action.type) {
            case CLICK_ADD: {
                return {
                    ...state,
                    age: state.age + 1
                }
            }
            case CLICK_SUB: {
               return {
                   ...state,
                   age: state.age - 1
               }
            }
            default:
                return state;
        }
    }
    export default changeAge;

       

    3.2、inputInfo_reducer.js

    import { INPUT_INFO } from "../actions/inputInfo_action";
    function initialState() {
        return {
            name: "ZhangSan"
        }
    }

    function inputInfo(state= initialState(),action) {
        switch (action.type) {
            case INPUT_INFO: {
                return {
                    ...state,
                    name: action.name
                }
            }
            default:
                return state;
        }
    }

    export default inputInfo;

      

    3.3、rootReducer.js

        

    (4)store.js文件

    import { createStore } from "redux";
    import rootReducer from "../reducer/rootReducer";

    const store = createStore(rootReducer);

    export default store;

    (5)组件

      5.1、Name组件(name.js)

    import React,{ Component } from "react";
    import PropTypes from "prop-types";

    import { connect } from "react-redux";

    class Name extends Component {
        render() {
            const { name } = this.props
            return (
                <div>
                    My name is <i>{ name }</i>
                </div>
            )
        }
    }
    Name.propTypes = {
        name: PropTypes.string.isRequired
    }

    const mapStateToProps = (state)=> {
        return {
            name: state.Name_store.name
        }
    }
    export default connect(mapStateToProps)(Name);

       5.2、Age组件(age.js)

    import React,{ Component } from "react";
    import PropTypes from "prop-types";
    import { connect } from "react-redux";
    import {clickAdd,clickSub } from "../actions/changeAge_action";

    class Age extends Component{
        constructor(props) {
            super(props);
            this.clickAdd = this.clickAdd.bind(this);
            this.clickSub = this.clickSub.bind(this);
        }
        render() {
            const { age } = this.props
            return (
                <div>
                    I am <i>{ age } </i>years old this year
                       
                    <button onClick={this.clickAdd }>Add Age</button>
                    <button onClick={this.clickSub }>Sub Age</button>
                </div>
            )
        }
        clickAdd(event) {
            this.props.dispatch(clickAdd());
        }
        clickSub(event) {
            this.props.dispatch(clickSub());
        }
    }

    Age.propTypes = {
        age: PropTypes.number.isRequired
    }

    const mapStateToProps = (state) => {
        return {
            age: state.Age_store.age
        }
    }

    export default connect(mapStateToProps)(Age);

       5.3、Form组件(form.js)

    import React,{Component} from "react";
    import {connect} from "react-redux";
    import { inputInfo } from "../actions/inputInfo_action";

    class Form extends Component {
        constructor(props) {
            super(props);
            this.clickSubmit = this.clickSubmit.bind(this);
        }
        render() {
            return (
                <div>
                    <input type={"text"} placeholder={"name"} id={"nameInput"}/>
                    <button onClick={ this.clickSubmit }>提交</button>
                </div>
            )
        }
        clickSubmit(event) {
            let name = document.getElementById('nameInput').value;
            console.log(name);
            this.props.dispatch(inputInfo(name));
        }
    }

    export default connect()(Form);

    (6)App.js

    import logo from './logo.svg';
    import './App.css';
    import Name from "./redux/components/name";
    import Age from "./redux/components/age";
    import Form from "./redux/components/form";
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <Name />
              <br/>
            <Age />
              <br/>
            <Form />
          </header>
        </div>
      );
    }

    export default App;

    (7)index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import { Provider } from "react-redux";
    import store from "./redux/store/store";

    ReactDOM.render(
       <Provider store={ store }>
          <App />
       </Provider>,
      document.getElementById('root')
    );

     

  • 相关阅读:
    ant-design-vue a-tree默认展开所有父节点不生效
    CSS模型简介
    一点BFC的看法
    css提高开发效率的必备代码
    CSS模型简介-逆战班
    CSS 样式:常用居中方法
    rem 自适应布局 js 代码
    CSS 样式 :position-absolute 绝对定位属性
    CSS 样式
    CSS样式字体初解
  • 原文地址:https://www.cnblogs.com/lone5wolf/p/15831837.html
Copyright © 2020-2023  润新知