如何使用带有 setState 的数组?
How to use an array with setState?
我目前正在使用以下方法将我的数组映射到 setState,但没有设置任何内容,也没有记录任何错误。如果我明确地逐行写出来,它就可以工作。关于如何解决这个问题有什么想法或建议吗?
用数组设置状态:(不设置状态)
const myData = ['message', 'photo', 'isLoggedInhoto'];
const newData = [];
{[...Array(myData.length)].map((x, index) =>
newData.push(myData[index])
)}
this.setState({
newData: localStorage.getItem(newData),
})
逐行(这有效并且确实设置状态):
this.setState({
message: localStorage.getItem('message'),
photo: localStorage.getItem('photo'),
isLoggedIn: localStorage.getItem('isLoggedIn')
})
您不能将数组用作对象的键和 getItem
的参数。
您需要遍历 newData
并使用 computed property name 语法:
newData.forEach(key => this.setState({ [key]: localStorage.getItem(key) }))
或者在重构代码时,您可以通过单个循环和单个 setState
调用来实现它:
const myData = ['message', 'photo', 'isLoggedInhoto']
const newData = {}
{[...Array(myData.length)].map((x, index) =>
newData[myData[index]] = localStorage.getItem(myData[index])
)}
this.setState(newData)
不幸的是,Javascript 不会按照您的代码假设的方式解构数组。您不能将数组设置为对象的键并将其扩展到数组中的所有项目。您的代码只是设置一个名为 newData
的键,而不是设置一个键数组。 Javascript 对象文字中的键不必被引用。这是使用字符串 "newData",而不是变量。
对于localStorage.getItem()
,第一个参数是字符串键名。无法通过使用数组作为键一次获取多个键。
这是一种干净的方法,使用 ES6 语法:
this.setState(
[ 'message', 'photo', 'isLoggedInhoto' ].reduce( ( memo, key ) => ({
...memo,
[ key ]: localStorage.getItem( key )
}), {} )
);
解释:
我们正在减少 一个数组,这听起来像它的作用。它将数组中的所有项目减少为一件事。第一个参数 memo
是 "accumulator",意思是我们正在减少和构建的东西,第二个参数是当前元素('message'
,'photo'
, 等等).
具有此语法 () => ({})
的箭头函数表示 return 一个对象。特别是包裹花括号的括号。如果没有括号换行,如 () => {}
,则大括号内的任何内容都将被解释为常规函数体。
此语法:
{ ...memo }
表示将旧对象memo
的内容复制到新对象中。这是 es6 传播运算符。
最后,要根据变量名设置键,将其包装在[]
中,如
{ [ key ]: ... }
所以如果key是'message
',它会创建一个对象{ message: ... }
整个代码会生成一个类似
的对象
{
message: localStorage.getItem('message'),
photo: localStorage.getItem('photo'),
isLoggedIn: localStorage.getItem('isLoggedIn')
}
然后传递给 setState
所以所有的键都设置正确。
此外,.map()
一般不应该这样使用。 .map()
用于 return 一个新数组,其中旧值映射到一些新值。从 .map()
中丢弃 return 意味着您使用了错误的循环范例。
[].forEach()
适用于没有 return 任何东西但有副作用的循环(比如推送到一些更高范围的数组)。但在这种情况下,两者都不理想,.reduce()
在语义上更正确地生成基于数组的对象。
您正在尝试创建一个新的状态对象,其中包含列表中的属性以及使用列表作为键从 localStorage
中提取的数据。
- 使用
Array#map
迭代列表
- 在每次迭代中使用列表中的键创建一个新对象,并且
从
localStorage
获取数据。不要忘记 JSON.parse()
如果
你已经存储了一个字符串化的 JSON 数据,
- Spread the array and create a new object using
Object#assign
.
- 将生成的对象设置为您所在的州。
代码:
const myData = ['message', 'photo', 'isLoggedInhoto'];
const state = Object.assign({}, ...myData.map((prop) => ({
[prop]: localStorage.getItem(prop) // or JSON.parse(localStorage.getItem(prop)) if your storing a JSON
})));
this.setState(state);
我目前正在使用以下方法将我的数组映射到 setState,但没有设置任何内容,也没有记录任何错误。如果我明确地逐行写出来,它就可以工作。关于如何解决这个问题有什么想法或建议吗?
用数组设置状态:(不设置状态)
const myData = ['message', 'photo', 'isLoggedInhoto'];
const newData = [];
{[...Array(myData.length)].map((x, index) =>
newData.push(myData[index])
)}
this.setState({
newData: localStorage.getItem(newData),
})
逐行(这有效并且确实设置状态):
this.setState({
message: localStorage.getItem('message'),
photo: localStorage.getItem('photo'),
isLoggedIn: localStorage.getItem('isLoggedIn')
})
您不能将数组用作对象的键和 getItem
的参数。
您需要遍历 newData
并使用 computed property name 语法:
newData.forEach(key => this.setState({ [key]: localStorage.getItem(key) }))
或者在重构代码时,您可以通过单个循环和单个 setState
调用来实现它:
const myData = ['message', 'photo', 'isLoggedInhoto']
const newData = {}
{[...Array(myData.length)].map((x, index) =>
newData[myData[index]] = localStorage.getItem(myData[index])
)}
this.setState(newData)
Javascript 不会按照您的代码假设的方式解构数组。您不能将数组设置为对象的键并将其扩展到数组中的所有项目。您的代码只是设置一个名为 newData
的键,而不是设置一个键数组。 Javascript 对象文字中的键不必被引用。这是使用字符串 "newData",而不是变量。
对于localStorage.getItem()
,第一个参数是字符串键名。无法通过使用数组作为键一次获取多个键。
这是一种干净的方法,使用 ES6 语法:
this.setState(
[ 'message', 'photo', 'isLoggedInhoto' ].reduce( ( memo, key ) => ({
...memo,
[ key ]: localStorage.getItem( key )
}), {} )
);
解释:
我们正在减少 一个数组,这听起来像它的作用。它将数组中的所有项目减少为一件事。第一个参数 memo
是 "accumulator",意思是我们正在减少和构建的东西,第二个参数是当前元素('message'
,'photo'
, 等等).
具有此语法 () => ({})
的箭头函数表示 return 一个对象。特别是包裹花括号的括号。如果没有括号换行,如 () => {}
,则大括号内的任何内容都将被解释为常规函数体。
此语法:
{ ...memo }
表示将旧对象memo
的内容复制到新对象中。这是 es6 传播运算符。
最后,要根据变量名设置键,将其包装在[]
中,如
{ [ key ]: ... }
所以如果key是'message
',它会创建一个对象{ message: ... }
整个代码会生成一个类似
的对象{
message: localStorage.getItem('message'),
photo: localStorage.getItem('photo'),
isLoggedIn: localStorage.getItem('isLoggedIn')
}
然后传递给 setState
所以所有的键都设置正确。
此外,.map()
一般不应该这样使用。 .map()
用于 return 一个新数组,其中旧值映射到一些新值。从 .map()
中丢弃 return 意味着您使用了错误的循环范例。
[].forEach()
适用于没有 return 任何东西但有副作用的循环(比如推送到一些更高范围的数组)。但在这种情况下,两者都不理想,.reduce()
在语义上更正确地生成基于数组的对象。
您正在尝试创建一个新的状态对象,其中包含列表中的属性以及使用列表作为键从 localStorage
中提取的数据。
- 使用
Array#map
迭代列表
- 在每次迭代中使用列表中的键创建一个新对象,并且
从
localStorage
获取数据。不要忘记JSON.parse()
如果 你已经存储了一个字符串化的 JSON 数据, - Spread the array and create a new object using
Object#assign
. - 将生成的对象设置为您所在的州。
代码:
const myData = ['message', 'photo', 'isLoggedInhoto'];
const state = Object.assign({}, ...myData.map((prop) => ({
[prop]: localStorage.getItem(prop) // or JSON.parse(localStorage.getItem(prop)) if your storing a JSON
})));
this.setState(state);