如何使用带有 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 中提取的数据。

  1. 使用 Array#map
  2. 迭代列表
  3. 在每次迭代中使用列表中的键创建一个新对象,并且 从 localStorage 获取数据。不要忘记 JSON.parse() 如果 你已经存储了一个字符串化的 JSON 数据,
  4. Spread the array and create a new object using Object#assign.
  5. 将生成的对象设置为您所在的州。

代码:

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);