【问题标题】:Modify only part of the state in a react-redux app仅修改 react-redux 应用程序中的部分状态
【发布时间】:2018-09-03 13:16:34
【问题描述】:

作为练习,我正在编写一个 react-redux 计算器应用程序。我的应用状态定义为:

const initialState = {
  operator1: "",  //first operand
  operator2: "",  //second operand
  currentOp: "",  // +, -, *, /
  display:"",     //the current calculator display
  currentOperator:1  //which operand is being entered right now
}

currentOp 保存计算器当前正在执行的操作的符号,当输入第一个操作数时,该符号为空。因此,当按下计算器的数字时,我需要更新显示,但不会丢失我的其他状态属性。我这样写了我的减速器:

import {NUMBER_PRESSED,OPERATION_PRESSED,EQUAL_PRESSED} from './actions';

const mainReducer = (state ={},action) =>
{
console.log("reducer called!");
console.log(action);
const newState = {};

//copy the operators to the new state. Only one will be changed. (Is this really necessary?)
newState.operator1 = state.operator1;
newState.operator2 = state.operator2;

switch(action.type)
{

    case NUMBER_PRESSED:
        if (state.currentOperator===1)
        {
            newState.operator1 = state.operator1 + action.payload;
            newState.display= newState.operator1;
        }
        if(state.currentOperator===2)
        {
            newState.operator2 = state.operator2 + action.payload;
            newState.display= newState.operator2;
        }

        //set the other properties of the state (Is this really necessary?)
        newState.currentOperator = state.currentOperator;
        newState.currentOp = state.currentOp;

        console.log("The new state is:");
        console.log(newState);
        return newState;

    case OPERATION_PRESSED:

        break;
    case EQUAL_PRESSED:

        break;

    default:
        return state;
}
}

export default mainReducer;

请注意,我还没有实现计算操作,只是更新了显示。如果我直接更改状态变量,计算器组件不会更新。可以理解,这是文档中解释的预期行为。但是,似乎我需要手动将整个状态复制到一个新变量中,以便保留下一个状态(注意“这真的有必要吗?”代码中的 cmets。 我复制所有应用程序的状态并返回一个全新的状态对象没有问题,但是在具有巨大状态树的大型应用程序上会发生什么?这是如何管理的?有没有办法只修改redux中的部分状态?

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    您可以使用扩展运算符之类的东西来复制整个对象,而无需手动设置每个对象:

    const x = state.someArray.slice();
    x[1] = "potato";
    return {...state, someArray:x}
    

    但要回答您的问题,是的,您必须在更改状态时制作一个全新的状态副本。这通常不是问题,也不需要太多时间。如果您的状态树很大,那么解决方案应该将该树拆分为单独的减速器,这样您只需在更改状态时复制和替换树的部分内容。

    【讨论】:

    • 但是不是所有的 reducer 都需要复制整个状态树,即使他们只使用其中的一部分?内存使用情况如何?如果我有一个巨大的状态树,当它在范围内时,复制它不会重复内存使用吗?
    • 你的商店树永远不应该特别大,它不应该包含记忆密集的东西,比如成千上万的搜索结果。如果你因为存储有大量数据而导致更改状态很慢,那么问题不在于树的重复,而在于你有太多的数据客户端并且你有东西在你不应该的商店里。
    • 基本上,如果你的 Redux 存储重复是问题所在,那么 Redux 存储的重复就不是问题了,哈哈。你应该重新审视你在那里存储的东西。 Javascript 浏览器引擎现在非常强大,所以如果您的商店合适,那么复制它应该不会很慢,而且它的内存占用应该非常小。
    • 如果不打算将它们存储在状态树中,如何处理显示数百条记录的客户端应用程序?
    • 这取决于用例,但理想情况下您根本不存储太多数据客户端,最好对数据进行分页。以小组的形式展示它,让他们根据需要请求一个新的集合,将当前的集合换成新的集合,这样他们就只能查看其中的一部分。但即使像 1,000 个 JSON 对象,也可能只有几百 KB,具体取决于每个对象的大小。这不会花费太多时间/内存来复制。如果你开始存储更多的东西,问题不在于如何管理 Redux 树的复制,而在于如何停止在客户端存储这么多东西。
    【解决方案2】:

    1:如果你的状态是decoupling,你应该使用combineReducers这是递归

    2:如果没有,你应该使用es6 destructuring

    3:更重要的是,你应该考虑你的状态结构。(取决于你的减速器代码,我建议......)

    以 2 为基础,例如

    const mainReducer = (state = {},action) => {
        switch(action.type) {
        case NUMBER_PRESSED:
            if (state.currentOperator===1) return {
               ...state,
               operator1: state.operator1 + action.payload,
               display: 'operator1'
            }
            if(state.currentOperator===2) return {
               ...state,
               operator2: state.operator2 + action.payload,
               display: 'operator2'
            }
            return state
        default: return state;
        }
    }
    

    如果正确的程序设计仍然很大......产品设计?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-20
      • 2017-06-03
      • 2017-02-03
      相关资源
      最近更新 更多