美文网首页
react中redux的使用

react中redux的使用

作者: 踩坑怪At芬达 | 来源:发表于2021-09-26 14:36 被阅读0次

以一个counter计数器组件为例,实现加减和异步加法

实现效果图如下:

image

index.jsx -- 入口


import React from 'react';
import {createStore,combineReducers,applyMiddleware} from 'redux';
import { Provider } from 'react-redux'
import thunkMiddleware from 'redux-thunk'

import * as reducers from './reducer/reducer.jsx';
import Counter from './components/Counter.jsx';
import LoginForm from './components/Login.jsx';

/**
* 创建store
* reducers是什么?你可以查看下面reducer.jsx代码内容
* combineReducers(reducers):是将多个reducer合并一起创建进store
* applyMiddleware(thunkMiddleware):注入一个可以实现异步dispatch的插件,
*/
let store = createStore(combineReducers(reducers),applyMiddleware(thunkMiddleware));

// <Provider>:将store透传进所有子组件内,所有子组件都可以通过 react-dedux的connect获取store
export default () => {
  return (
    <Provider store={store}>
        <Counter/>
    </Provider>
  );
};

Counter.jsx -- 计数器组件代码

import React from 'react';
import { connect } from 'react-redux'
import {AddDelay,Add,Dec} from '../reducer/action.jsx';


class Counter extends React.Component{
  constructor(props){
    super(props);
  }

  render(){
    const {reCounter,dispatch}=this.props;
    return (
      <div className={'flex-row flex-cross-center form'}>
        <p>当前计数器:{reCounter.value}</p>
        {/* 点击后计数器+1 */}
        <button onClick={()=>{dispatch( Add(1) )}}>加1</button>
        <button onClick={()=>{dispatch( Dec(1) )}}>减1</button>
         {/* 点击后计数器会在2秒后 +2 用来模拟接口调用 */}
        <button onClick={()=>{ dispatch( AddDelay(2,2000) )}}>
          {reCounter.loading?"loading":"加2 延迟2秒触发"}
        </button>
      </div>
    );
  }
}

/**
 * mapStateToProps的作用是将store传递进来的state,进行筛选后暴露给组件
 * 这里仅仅把store里面reCounter这个对象暴露给Countre组件
 * 所以Counter内可以通过 this.props.reCounter 获取到这个对象
 * state:store传递进来的所有reducer
 * return {} 你可以把你需要暴露给组件的对象筛选return,当然也可以直接将整个state return
 */
function mapStateToProps(state) {
  return  {reCounter:state.reCounter};
}

/**
 * connect作用是将store和当前组件进行捆绑
 * mapStateToProps 函数作用是处理store传入的state对象然后选择需要暴露给组件用的state对象
 */
export default connect(mapStateToProps)(Counter)


redcuer.jsx -- 存放所有redcuer


/**
 * 处理加减法
 */
export function reCounter(state = {value:0,loading:false}, action) {
  let value = typeof action.value === 'undefined' ? 1 : action.value;
  switch (action.type) {
    case 'COUNTER_LOADING': return {...state, loading:action.value };
    case 'COUNTER_ADD':     return {...state, value:state.value + value };
    case 'COUNTER_DEC':     return {...state, value:state.value - value };
    default: return state;
  }
}

action.jsx -- 存放所有被组件直接使用的action,为什么需要action这一层,我这里做了个演示,一来是为了避免使用 dispatch({type:"消息名称",value:""}) 这种难看的写法

二来是为了能统一处理一条消息的封装和发送


/**
 * value:增加的值
 * time:延迟多少ms触发
 */
export function AddDelay(value,time) {
  return (dispatch, getState) => {
    return new Promise(reslove => {
      dispatch({type:'COUNTER_LOADING',value:true});
      setTimeout(() => {
        dispatch({ type: 'COUNTER_ADD', value: value });
        dispatch({type:'COUNTER_LOADING',value:false});
        reslove();
      }, time);
    })
  }
}

/**
 * value:增加的值
 */
export function Add(value) {
  return (dispatch, getState) => {
    return new Promise(reslove => {
      dispatch({ type: 'COUNTER_ADD', value: value });
      reslove();
    })
  }
}
/**
 * value:减少的值
 */
export function Dec(value) {
  return (dispatch, getState) => {
    return new Promise(reslove => {
      dispatch({ type: 'COUNTER_DEC', value: value });
      reslove();
    })
  }
}

常见问题

阻塞式dispatch更新值方法

假设我们reducer管理一个叫user的对象{name:"姓名",detail:"我是姓名"}
在组件内有一个方法用来监听name是否发生改变,一旦发生改变就重新设置detail的值
当用户输入name发生变化时需要将detail设置为 我是${name}

一开始你可能想这样处理:

const User=(props)=>{
  const onNameChange= async (e)=>{
    //更新user下name属性
    await dispatch({...props.user,name:e.target.value});
   // 此处的监听可能存在于子组件中,这里为了方便展示所以直接下载了dispatch后
    await listener_nameChange(e.target.value);
    console.log(props.user);
  }

  //监听到name发生变更后,立刻更新了detail的值
 const listener_nameChange = async (newValue)=>{
    await dispatch({...props.user,detail:`i am ${newValue}`})
 }

  return (
    <div>
      <Input onChange={onNameChange} value={props.user.name} />
    </div>
  )
}

这里的log打印结果显然最终是detail发生了变更而name没有

解决方法

const User=(props)=>{
  onNameChange(e){
    //更新user下name属性
    dispatch({...props.user,name:e.target.value});
  }
   
  listener_nameChange(newValue){
    dispatch({...props.user,detail:`i am ${newValue}`})
  }
   // ✅ 正确方式应该在props值发生变更时监听,并且处理
  useEffect(()=>{
    listener_nameChange(props.user.name)
  },[props.user.name)
  

  return (
    <div>
      <Input onChange={onNameChange} value={props.user.name} />
      <Input value={props.user.detail} />
    </div>
  )
}

相关文章

  • react-redux

    使用react-redux,可以更方便的使用redux开发 先install react-redux使用react...

  • redux

    单独使用redux redux是核心库 与react配合使用redux 安装react-redux react-r...

  • 一个完整小巧的Redux全家桶项目

    OneArticle: 使用React-Native开发,使用Redux,React-Redux,Redux-Pe...

  • redux note(一)

    redux 搭配 React使用 Redux和React之间没有关系,Redux支持React, Angular,...

  • react-redux框架之connect()与Provider

    react-redux 在react-redux 框架中,给我提供了两个常用的API来配合Redux框架的使用,其...

  • React-redux的使用

    React-redux是一个第三方模块,它可以帮我们在react中更方便的使用redux,使用React-redu...

  • 深入解析React-redux插件入门

    react-redux是使用redux开发react时使用的一个插件,另外插一句,redux不是react的产品,...

  • React-redux插件入门实战

    react-redux是使用redux开发react时使用的一个插件,另外插一句,redux不是react的产品,...

  • react-redux

    redux 全局状态管理 react-redux 优化模块 优化redux的使用过程 通过react-redux ...

  • 20.redux使用

    react-redux 使用一个react-redux 的库使得redux的使用更简洁,它提供了provider和...

网友评论

      本文标题:react中redux的使用

      本文链接:https://www.haomeiwen.com/subject/ljgjzctx.html