在不改变整个状态的情况下改变状态的数组 (REACT/REDUX) [英] Change state's array without changing the whole state (REACT / REDUX)

查看:34
本文介绍了在不改变整个状态的情况下改变状态的数组 (REACT/REDUX)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要买的东西的清单(对于我用 React 制作的一个小游戏),它是一个数组.它处于一种称为市场"的状态.我还有另一个,我想将所有价值随机化并将它们存放在另一个状态.

I got a list of things to buy (for a little game i'm making with React) who is an array. It's in a state called "Market". And i have the other one, where i want to randomise all the value and stock them in another state.

这是我的市场列表:

let marketList = [
  {"name": 'product name', "qty": 0, "minPrice": 10, "maxPrice": 100, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 30, "maxPrice": 200, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 100, "maxPrice": 1500, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 200, "maxPrice": 4000, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 50, "maxPrice": 6000, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 1, "maxPrice": 400, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 60, "maxPrice": 3450, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 2, "maxPrice": 120, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 8, "maxPrice": 600, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 120, "maxPrice": 3200, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 35, "maxPrice": 100, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 300, "maxPrice": 12000, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false},
  {"name": 'product name', "qty": 0, "minPrice": 1, "maxPrice": 80, "currentPrice": 0, "historyPrice": [], "historyQty": [], "available": false}
];

我想随机化其中的所有值并将随机列表存储在名为明天"的状态中,以便能够提供有关下一个价格的提示.这是我随机化列表的助手.

I want to randomise all the value in it and store the randomised list in a state called "Tomorrow" to be able to gives hints about the next prices. This is my helpers to randomise the lists.

export function randomiseMarketList(list, day = 0){
  for(let i = 0; i < list.length; i++) {
    let item = list[i];
    let historyQtylength = item.historyQty.length;
    let random = randomAlgo(day);

    item.currentPrice = Math.floor(Math.random() * (item.maxPrice - item.minPrice)) + item.minPrice;
    item.qty = random;
    item.available = !(day == 0 || item.qty < 1);

    item.historyPrice.push(item.currentPrice);
    item.historyQty.push(item.qty);
  } 
  return list;
}

function randomAlgo(day) {
  let quart = Math.floor(Math.random() * 4);
  let multiple = Math.floor(Math.random() * 10);
  let maxQuart = Math.floor(Math.random() * (quart * multiple * day));
  let minQuart = Math.floor(Math.random() * (quart * multiple));
  return Math.floor(Math.random() * (maxQuart - minQuart)) + minQuart;
}

这是我的 Tomorrow 减速机:

And this is my Tomorrow reducer:

import { ACTIONS } from '../utils/consts';
import { randomiseMarketList } from '../utils/helpers';

var initialState = {
  currentPlaceList: []
};

export function tomorrow(state = initialState, action = '') {
  switch (action.type) {

    case ACTIONS.BUILD_TOMORROW_LIST:
      console.log(action);
      let listToRandom = action.list.slice();
      let randomactionList = randomiseMarketList([...listToRandom], action.day);
      console.log(randomactionList);
      let newList = Object.assign({}, state, { currentPlaceList: randomactionList });
      return newList;

    default:
      return state;
  }
}

正如您在我的 ACTIONS.BUILD_TOMORROW_LIST 中看到的那样,我首先通过控制台记录操作以检查值,然后在我记录随机列表后,它们始终具有相同的值.我不明白为什么如果我更改它们,它们具有相同的值.

As you can see in my ACTIONS.BUILD_TOMORROW_LIST, i console log the action to check the value at first, and after i log the randomised list, who always has the same values. I don't understand here why they have the same values if i changed them.

我以为是因为数组完全一样,我直接改变了状态(不明白为什么).我将列表作为由值和扩展运算符构建的新数组传递,也不起作用.我尝试创建此数组的副本,但也不起作用.

I thought it was because the array was the absolute same and i changed the state directly (don't understand why). I passed the list as a new array built by the values and the spread operator, doesn't work either. I tried to create a copy of this array, doesn't work too.

当我们点击留在此处"操作时,明天的列表将用于替换当前市场的列表.

The list in the tomorrow will be used to replace the current Market's list when we click on the "stay here" action.

handleStayHere(e) {
    const { dispatch, status, tomorrow, market } = this.props;
    dispatch( MarketActions.changeWholeList(tomorrow.currentPlaceList) );
    dispatch( StatusActions.changeDay( status.day + 1 ) );
    dispatch( TomorrowActions.buildTomorrowList([...market], status.day + 1) );
  }

MarketActions.changeWholeList 操作运行良好,但我无法正确存储明天的列表.

The MarketActions.changeWholeList action works well, but i can't store correctly the tomorrow list.

感谢您的帮助!

推荐答案

看起来您没有更改列表的元素,而是在随机生成器中对它们进行了变异.这可能会导致奇怪的行为(昨天调试的问题=)))我认为最好将列表值映射到 randomiseMarketList 中的新对象,因此您无需担心项目对象是与数组切片相同——它只是另一个对象引用.

Looks like you don't change list's elements but mutate them in randomizer. This could lead to bizarre behaviour (debugged problem with this yesterday =)) ) I think it's better to map list values to new objects in randomiseMarketList, so you don't need to worry about item objects being the same and array slicing — it will be just plainly another object reference.

randomiseMarketList(list, day = 0){
  return list.map(item => {
    //it case there's another meaningful properties in item
    ...item,
    qty: randomAlgo(day),
    currentPrice: Math.floor(Math.random() * (item.maxPrice - item.minPrice)) + item.minPrice,
    available: !(day == 0 || item.qty < 1),
    historyPrice: [...item.historyPrice, item.currentPrice],
    historyQty: [...item.historyQty, item.qty],
})

然后在减速器中

function tomorrow(state = initialState, action) {
  switch (action.type) {
    case ACTIONS.BUILD_TOMORROW_LIST:
      const currentPlaceList = randomiseMarketList(action.list, action.day);
      return {...state, currentPlaceList}

    default:
      return state;
  }
}

另一个,在 reducer 中,您正在对数组进行切片,然后将其解构为另一个数组——这看起来像是双重工作,没有结果.

Another one, in reducer you're slicing array and then destructure it to another array — this looks like double work with no outcome.

这篇关于在不改变整个状态的情况下改变状态的数组 (REACT/REDUX)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆