Javascript 如何在redux中更新特定数组项内的单个值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35628774/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to update single value inside specific array item in redux
提问by Ilja
I have an issue where re-rendering of state causes ui issues and was suggested to only update specific value inside my reducer to reduce amount of re-rendering on a page.
我有一个问题,重新渲染状态会导致 ui 问题,并且建议仅更新我的减速器中的特定值以减少页面上的重新渲染量。
this is example of my state
这是我所在州的例子
{
name: "some name",
subtitle: "some subtitle",
contents: [
{title: "some title", text: "some text"},
{title: "some other title", text: "some other text"}
]
}
and I am currently updating it like this
我目前正在像这样更新它
case 'SOME_ACTION':
return { ...state, contents: action.payload }
where action.payload
is a whole array containing new values. But now I actually just need to update text of second item in contents array, and something like this doesn't work
其中action.payload
是包含新值的整个数组。但现在我实际上只需要更新内容数组中第二项的文本,而这样的事情是行不通的
case 'SOME_ACTION':
return { ...state, contents[1].text: action.payload }
where action.payload
is now a text I need for update.
action.payload
现在我需要更新的文本在哪里。
采纳答案by Clarkie
You could use the React Immutability helpers
你可以使用React Immutability helpers
import update from 'react-addons-update';
// ...
case 'SOME_ACTION':
return update(state, {
contents: {
1: {
text: {$set: action.payload}
}
}
});
Although I would imagine you'd probably be doing something more like this?
虽然我想你可能会做更多这样的事情?
case 'SOME_ACTION':
return update(state, {
contents: {
[action.id]: {
text: {$set: action.payload}
}
}
});
回答by Fatih Erikli
You can use map
. Here is an example implementation:
您可以使用map
. 这是一个示例实现:
case 'SOME_ACTION':
return {
...state,
contents: state.contents.map(
(content, i) => i === 1 ? {...content, text: action.payload}
: content
)
}
回答by Yuya
You don't have to do everything in one line:
您不必在一行中完成所有操作:
case 'SOME_ACTION':
const newState = { ...state };
newState.contents =
[
newState.contents[0],
{title: newState.contnets[1].title, text: action.payload}
];
return newState
回答by Ivan V.
Very late to the party but here is a generic solution that works with every index value.
聚会很晚,但这里有一个适用于每个索引值的通用解决方案。
You create and spread new array from the old array up to the
index
you want to change.Add the data you want.
Create and spread new array from the
index
you wanted to change to the end of the array
您创建并将新数组从旧数组扩展到
index
要更改的数组。添加您想要的数据。
创建并传播新数组,从
index
要更改的数组到数组末尾
let index=1;// probabbly action.payload.id
case 'SOME_ACTION':
return {
...state,
contents: [
...state.contents.slice(0,index),
{title: "some other title", text: "some other text"},
...state.contents.slice(index+1)
]
}
Update:
更新:
I have made a small module to simplify the code, so you just need to call a function:
我做了一个小模块来简化代码,所以你只需要调用一个函数:
case 'SOME_ACTION':
return {
...state,
contents: insertIntoArray(state.contents,index, {title: "some title", text: "some text"})
}
For more examples, take a look at the repository
有关更多示例,请查看存储库
function signature:
函数签名:
insertIntoArray(originalArray,insertionIndex,newData)
回答by Erfan226
In my case I did something like this, based on Luis's answer:
就我而言,根据路易斯的回答,我做了类似的事情:
...State object...
userInfo = {
name: '...',
...
}
...Reducer's code...
case CHANGED_INFO:
return {
...state,
userInfo: {
...state.userInfo,
// I'm sending the arguments like this: changeInfo({ id: e.target.id, value: e.target.value }) and use them as below in reducer!
[action.data.id]: action.data.value,
},
};
回答by Luis Rodriguez
I believe when you need this kinds of operations on your Redux state the spread operator is your friendand this principal applies for all children.
我相信当你需要在你的 Redux 状态上进行这种操作时,spread 运算符是你的朋友,这个原则适用于所有孩子。
Let's pretend this is your state:
让我们假设这是您的状态:
const state = {
houses: {
gryffindor: {
points: 15
},
ravenclaw: {
points: 18
},
hufflepuff: {
points: 7
},
slytherin: {
points: 5
}
}
}
And you want to add 3 points to Ravenclaw
而你想给拉文克劳加3分
const key = "ravenclaw";
return {
...state, // copy state
houses: {
...state.houses, // copy houses
[key]: { // update one specific house (using Computed Property syntax)
...state.houses[key], // copy that specific house's properties
points: state.houses[key].points + 3 // update its `points` property
}
}
}
By using the spread operator you can update only the new state leaving everything else intact.
通过使用扩展运算符,您可以仅更新新状态,而其他所有内容均保持不变。
Example taken from this amazing article, you can find almost every possible option with great examples.
来自这篇精彩文章的示例,您可以找到几乎所有可能的选项以及很好的示例。
回答by TazExprez
This is how I did it for one of my projects:
这就是我为我的一个项目所做的:
const markdownSaveActionCreator = (newMarkdownLocation, newMarkdownToSave) => ({
type: MARKDOWN_SAVE,
saveLocation: newMarkdownLocation,
savedMarkdownInLocation: newMarkdownToSave
});
const markdownSaveReducer = (state = MARKDOWN_SAVED_ARRAY_DEFAULT, action) => {
let objTemp = {
saveLocation: action.saveLocation,
savedMarkdownInLocation: action.savedMarkdownInLocation
};
switch(action.type) {
case MARKDOWN_SAVE:
return(
state.map(i => {
if (i.saveLocation === objTemp.saveLocation) {
return Object.assign({}, i, objTemp);
}
return i;
})
);
default:
return state;
}
};