跳到主要内容

语法

2024年02月26日
柏拉文
越努力,越幸运

一、redux 同步


二、redux 异步


三、redux legacy 同步


细节
  1. Redux每一次state更新,都会重新render ,大型应用中会造成不必要的重复渲染

  2. Redux只是个纯粹的状态管理器,默认只⽀持同步,实现异步任务 ⽐如延迟,⽹络请求,需要中间件的⽀持

1. 安装redux

yarn add redux -S

2. store --> index.js 用于创建Store

import { createStore, combineReducers } from "redux";
import { countReducer, usernameReducer } from "./reducer";

const reducer = combineReducers({
count:countReducer,
username:usernameReducer
});

const store = createStore(reducer)
export default store;

3. store --> reducer.js 用于统一维护Reducer

export const countReducer = (state=0,action)=>{
switch(action.type){
case "add":
return state+action.data;
case "min":
return state-action.data;
default:
return state;
}
}

export const usernameReducer = (state='柏拉文',action)=>{
switch(action.type){
case "change":
return action.data;
default:
return state;
}
}

4. index.js 入口文件全局订阅Store

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './store'

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

render();
// 订阅 store
store.subscribe(render);

5. app.js app组件使用Store以及派发Store

import store from './store'

function App() {
const state = store.getState();
const handleChangeUsername = (value)=>{
// store 派发 修改 username Reducer
store.dispatch({type:'change',data:value});
}
const handleAddCount = (value)=>{
// store 派发 修改 count Reducer
store.dispatch({type:'add',data:value});
}
const handleMinCount = (value)=>{
// store 派发 修改 count Reducer
store.dispatch({type:'min',data:value});
}
return (
<div className="App">
<h3>{state.username}</h3>
<h3>{state.count}</h3>
<div>
<button onClick={()=>handleChangeUsername('柏拉文修改')}>修改 username</button>
<button onClick={()=>handleAddCount(1)}>增加 count</button>
<button onClick={()=>handleMinCount(1)}>减少 count</button>
</div>
</div>
);
}

export default App;

四、redux legacy 异步


细节
  1. Redux只是个纯粹的状态管理器,默认只⽀持同步,实现异步任务 ⽐如延迟,⽹络请求,需要中间件的⽀持,⽐如我们试⽤最简单的redux-thunkredux-logger

1. 安装reduxredux-thunkredux-logger

yarn add redux redux-thunk redux-logger -S

2. store --> index.js 用于创建Store

import { createStore, combineReducers,applyMiddleware } from "redux";
import { countReducer, usernameReducer } from "./reducer";
import Thunk from 'redux-thunk';
import Logger from 'redux-logger';

const reducer = combineReducers({
count:countReducer,
username:usernameReducer
});

const store = createStore(reducer,applyMiddleware(Logger,Thunk))

export default store;

3. store --> reducer.js 用于统一维护Reducer

export const countReducer = (state=0,action)=>{
switch(action.type){
case "add":
return state+action.data;
case "min":
return state-action.data;
default:
return state;
}
}

export const usernameReducer = (state='柏拉文',action)=>{
switch(action.type){
case "change":
return action.data;
default:
return state;
}
}

4. index.js 入口文件全局订阅Store

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './store'

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

render();
// 订阅 store
store.subscribe(render);

5. app.js app组件使用Store以及派发Store

import store from './store'

function App() {
const state = store.getState();
console.log(state);
const handleChangeUsername = (value) => {
// store 派发 修改 username Reducer
store.dispatch({ type: 'change', data: value });
}
const handleChangeUsernameAsync = (value) => {
// store 派发 修改 username Reducer
store.dispatch((dispatch) => {
setTimeout(() => {
dispatch({ type: 'change', data: value });
}, 300);
});
}
const handleAddCount = (value) => {
// store 派发---同步增加 count Reducer
store.dispatch({ type: 'add', data: value });
}
const handleMinCount = (value) => {
// store 派发---同步减少 count Reducer
store.dispatch({ type: 'min', data: value });
}
const handleAddCountAsync = (value) => {
// store 派发---异步增加 count Red ucer
store.dispatch((dispatch) => {
setTimeout(() => {
dispatch({ type: 'add', data: value });
}, 300);
});
}
const handleMinCountAsync = (value) => {
// store 派发---异步减少 count Reducer
store.dispatch((dispatch) => {
setTimeout(() => {
dispatch({ type: 'min', data: value });
}, 300);
});
}
return (
<div className="App">
<h3>{state.username}</h3>
<h3>{state.count}</h3>
<div>
<button onClick={() => handleChangeUsername('柏拉文修改')}>同步修改 username</button>
<button onClick={() => handleChangeUsernameAsync('柏拉文修改')}>异步修改 username</button>
<button onClick={() => handleAddCount(1)}>同步增加 count</button>
<button onClick={() => handleMinCount(1)}>同步减少 count</button>
<button onClick={() => handleAddCountAsync(1)}>异步增加 count</button>
<button onClick={() => handleMinCountAsync(1)}>异步减少 count</button>
</div>
</div>
);
}

export default App;

五、redux react-redux legacy 同异步


5.1 认识

由于 Redux 通过在入口文件中进行订阅 store.subscribe(render) 之后, 在需要状态的组件中, 引入 store 文件即可访问、更新状态。那这样的话无法做到精确更新, 比如 A 组件需要状态 aB 组件需要状态 b ,那么改变 a,只希望 A 组件更新,不希望 B 组件更新。所以, React-Redux 应运而生。

React-Redux 是连接 React 应用和 Redux 状态管理的桥梁, React-redux 主要专注两件事,一是如何向 React 应用中注入 redux 中的 Store ,二是如何根据 Store 的改变,把消息派发给应用中需要状态的每一个组件。

  1. React 注入 redux 中的 Store: Redux 提供了一个 Provider 组件, 可以全局注入 redux 中的 store ,所以使用者需要把 Provider 注册到根部组件中。Provider 作用就是保存 redux 中的 store ,分配给所有需要 state 的子孙组件。

  2. 订阅 Store 中的 state 变化, 派发给应用中需要状态的每一个组件: Redux 提供了一个高阶组件 connect, 被 connect 包装后组件将获得如下功能:

    • 能够从 props 中获取改变 state 的方法 Store.dispatch

    • 如果 connect 有第一个参数,那么会将 redux state 中的数据,映射到当前组件的 props 中,子组件可以使用消费

    • 当需要的 state ,有变化的时候,会通知当前组件更新,重新渲染视图

React-Recut 通过 Provider 组件解决了 Redux 状态共享的问题, 通过 connect 高阶组件订阅状态, 并通过传递第一个参数 mapStateToProps 来订阅具体依赖状态, 只有订阅具体的依赖状态发生变化, 才会触发业务组件更新视图。当这个参数没有的时候,当前组件不会订阅 store 的改变。

5.2 语法

1. 安装reduxreact-redux,redux-thunkredux-logger

yarn add redux redux-thunk redux-logger react-redux -S

2. store --> index.js 用于创建Store

import { createStore, combineReducers,applyMiddleware } from "redux";
import { countReducer, usernameReducer } from "./reducer";
import Thunk from 'redux-thunk';
import Logger from 'redux-logger';

const reducer = combineReducers({
count:countReducer,
username:usernameReducer
});

const store = createStore(reducer,applyMiddleware(Thunk,Logger))

export default store;

3. store --> reducer.js 用于统一维护Reducer

export const countReducer = (state=0,action)=>{
switch(action.type){
case "add":
return state+action.data;
case "min":
return state-action.data;
default:
return state;
}
}

export const usernameReducer = (state='柏拉文',action)=>{
switch(action.type){
case "change":
return state+action.data;
default:
return state;
}
}

4. index.js 入口文件通过Provider传递Store

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


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

render();

5. app.js app组件使用Store以及派发Store

  • mapDispatchToProps对象写法

    import { connect } from 'react-redux';

    function App(props) {
    const handleChangeUsername = (value) => {
    // store 派发 修改 username Reducer
    props.change(value);
    }
    const handleChangeUsernameAsync = (value) => {
    // store 派发 修改 username Reducer
    props.changeSync(value);
    }
    const handleAddCount = (value) => {
    // store 派发---同步增加 count Reducer
    props.add(value);
    }
    const handleMinCount = (value) => {
    // store 派发---同步减少 count Reducer
    props.min(value);
    }
    const handleAddCountAsync = (value) => {
    // store 派发---异步增加 count Red ucer
    props.addSync(value);
    }
    const handleMinCountAsync = (value) => {
    // store 派发---异步减少 count Reducer
    props.minSync(value);
    }
    return (
    <div className="App">
    <h3>{props.username}</h3>
    <h3>{props.count}</h3>
    <div>
    <button onClick={() => handleChangeUsername('柏拉文修改')}>同步修改 username</button>
    <button onClick={() => handleChangeUsernameAsync('柏拉文修改')}>异步修改 username</button>
    <button onClick={() => handleAddCount(1)}>同步增加 count</button>
    <button onClick={() => handleMinCount(1)}>同步减少 count</button>
    <button onClick={() => handleAddCountAsync(1)}>异步增加 count</button>
    <button onClick={() => handleMinCountAsync(1)}>异步减少 count</button>
    </div>
    </div>
    );
    }

    const mapStateToProps = (state, currentProps) => {
    return {
    count: state.count,
    username: state.username
    }
    }
    const mapDispatchToProps = {
    add: (value) => ({ type: 'add', data: value }),
    min: (value) => ({ type: 'min', data: value }),
    change: (value) => ({ type: 'change', data: value }),
    addSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'add', data: value });
    }, 300);
    }
    },
    minSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'min', data: value });
    }, 300);
    }
    },
    changeSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'change', data: value });
    }, 300);
    }
    }
    }
    const ConnectApp = connect(mapStateToProps, mapDispatchToProps)(App);

    export default ConnectApp;
  • mapDispatchToProps函数写法

    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';

    function App(props) {
    const handleChangeUsername = (value) => {
    // store 派发 修改 username Reducer
    props.change(value);
    }
    const handleChangeUsernameAsync = (value) => {
    // store 派发 修改 username Reducer
    props.changeSync(value);
    }
    const handleAddCount = (value) => {
    // store 派发---同步增加 count Reducer
    props.add(value);
    }
    const handleMinCount = (value) => {
    // store 派发---同步减少 count Reducer
    props.min(value);
    }
    const handleAddCountAsync = (value) => {
    // store 派发---异步增加 count Red ucer
    props.addSync(value);
    }
    const handleMinCountAsync = (value) => {
    // store 派发---异步减少 count Reducer
    props.minSync(value);
    }
    return (
    <div className="App">
    <h3>{props.username}</h3>
    <h3>{props.count}</h3>
    <div>
    <button onClick={() => handleChangeUsername('柏拉文修改')}>同步修改 username</button>
    <button onClick={() => handleChangeUsernameAsync('柏拉文修改')}>异步修改 username</button>
    <button onClick={() => handleAddCount(1)}>同步增加 count</button>
    <button onClick={() => handleMinCount(1)}>同步减少 count</button>
    <button onClick={() => handleAddCountAsync(1)}>异步增加 count</button>
    <button onClick={() => handleMinCountAsync(1)}>异步减少 count</button>
    </div>
    </div>
    );
    }

    const mapStateToProps = (state, currentProps) => {
    return {
    count: state.count,
    username: state.username
    }
    }
    const mapDispatchToProps = (dispatch) => {
    const result = {
    add: (value) => ({ type: 'add', data: value }),
    min: (value) => ({ type: 'min', data: value }),
    change: (value) => ({ type: 'change', data: value }),
    addSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'add', data: value });
    }, 300);
    }
    },
    minSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'min', data: value });
    }, 300);
    }
    },
    changeSync: (value) => {
    return (dispatch) => {
    setTimeout(() => {
    dispatch({ type: 'change', data: value });
    }, 300);
    }
    }
    }
    const resultBind = bindActionCreators(result,dispatch);
    return {
    dispatch,
    ...resultBind
    }
    }

    const ConnectApp = connect(mapStateToProps, mapDispatchToProps)(App);

    export default ConnectApp;