React -如何在UseEffect中使用useState更新对象数组中的特定字段



首先,我使用useState创建一个对象数组address

useEffect中,我想在我从API获得响应后更新address

address的最终值应为

[
{ id: "unit", label: "Unit", value: "Unit 1" },
{ id: "floor", label: "Floor", value: "Floor 1" },
{ id: "block", label: "Block", value: "Block 1" }
]

我该怎么做?

App.js

import "./styles.css";
import React, { useState, useEffect } from "react";
export default function App() {
const [address, setAddress] = useState([
// the value will be updated in useEffect
{ id: "unit", label: "Unit", value: "" },  // Value should be Unit 1
{ id: "floor", label: "Floor", value: "" },// Value should be Floor 1
{ id: "block", label: "Block", value: "" } // Value should be Block 1
]);
useEffect(() => {
// let's pretent there is api GET request
let responseData = {
en: {
unit: "Unit 1",
floor: "Floor 1",
Block: "Block 1"
}
// other language address which can be ignored
};
// How to update the update of address below??
}, []);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}

CodeSandbox: https://codesandbox.io/s/cranky-microservice-qjuhh?file=/src/App.js

假设address中的所有项目在responseData中都有一个匹配的值,您可以使用:

useEffect(() => {
// let's pretent there is api GET request
let responseData = {
en: {
unit: "Unit 1",
floor: "Floor 1",
Block: "Block 1"
}
// other language address which can be ignored
};

setAddress((address) => (
address.map((item) => ({ ...item, value: responseData.en[item.id] }))
));
}, []);

上面的代码循环遍历address数组,并将每个元素映射到responseData.en中具有更新值的元素。

我使用回调的原因是因为如果新状态依赖于以前的状态,你应该使用回调。由于您只想更新一个项目的单个属性(而不是完全替换状态),因此新状态依赖于旧状态,因此您使用回调。

您可以通过以下方式更新:

useEffect(() => {
// let's pretent there is api GET request
let responseData = {
en: {
unit: "Unit 1",
floor: "Floor 1",
Block: "Block 1"
}
// other language address which can be ignored
};
// How to update the update of address below??
setAddress((prevAddress) => [
{
...prevAddress[0],
value: responseData.en.unit
},
{
...prevAddress[0],
value: responseData.en.floor
},
{
...prevAddress[0],
value: responseData.en.Block
}
]);
}, []);

供参考:https://codesandbox.io/s/hopeful-silence-gs1yq?file=/src/App.js:425-1015

  1. 获取responseData中与语言分离的对象

  2. map重写状态数组,用responseData的新值创建一个新的对象数组。

const data = [{ id: "unit", label: "Unit", value: "" },{ id: "floor", label: "Floor", value: "" },{ id: "block", label: "Block", value: "" }];
const responseData = {en: {unit: "Unit 1",floor: "Floor 1",block: "Block 1"}};
const obj = Object.values(responseData)[0];
const result = data.map(({ id, value, ...rest }) => {
return { id, value: obj[id], ...rest };
});
console.log(result);

像这样尝试,如果en可用,它将使用en,否则使用第一个可用的语言

useEffect(() => {
// let's pretent there is api GET request
let responseData = {
en: {
unit: "Unit 1",
floor: "Floor 1",
Block: "Block 1"
}
// other language address which can be ignored
};
let languagePriority = null
const availableLangs = Object.keys(responseData)
if (responseData.en) {
languagePriority = 'en'
}
if (!responseData.en && availableLangs.length) {
languagePriority = availableLangs[0]
}
if (languagePriority) {
const responseKeys = 
Object.keys(responseData[languagePriority])
const addressCopy = [...address]
responseKeys.forEach(item => {
addressCopy.find(addItem => {
if (addItem.id === item) {
addItem.value = response.en[item]
}
})
})
setAddress(addressCopy)
}

// How to update the update of address below??
}, []);

最新更新