当您单击复选框时,我正在尝试更改其值。但是由于某种原因,更改不会再次呈现。为什么?
样本数据(props.data):
{
"school": {
"checkDocuments": [
{
'label': 'license',
'check': false
},
{
'label': 'identification',
'check': false
},
{
'label': 'phone',
'check': false
},
],
"section": "escuela"
},
"collage": {
"checkDocuments": [
{
'label': 'license',
'check': false
}
],
"section": "universidad"
}
这是我的组件:
export const Verificardocuments = props => {
const [documents, setDocuments] = useState(props.data);
updateDataDocument = (section, index) => {
console.log(section, index);
documents[section].checkDocuments[index].check =
!documents[section].checkDocuments[index].check;
setDocuments(documents);
}
return
<List>
{
/* escuela,universidad => "section" key */
Object.keys(documents).map((section, i) => {
return (
<View key={i}>
<ListItem itemDivider >
<Text>{documents[section].section}</Text>
</ListItem>
{documents[section].checkDocuments.map((document, j) => {
return (
<ListItem onPress={() => updateDataDocument(section, j)} key={j} >
<CheckBox checked={document.check} color="blue" />
<Body>
<Text>{document.label}</Text>
</Body>
</ListItem>)
})}
</View>
)
})
}
</List>
}
我不确定是否正在以最佳方式更新数组中包含的元素。
这里是一种方法。
由于您的数据结构有些复杂/很大,因此您需要为其中的每个嵌套对象或数组创建一个副本。完成此操作后,您可以安全地更新副本,而无需更改原始变量(状态)。然后,将副本更新为您想要的新状态,您只需使用它来设置新状态。
updateDataDocument = (section, index) => {
const obj = {...documents}; // Copy the documents object
const arr = [...obj[section].checkDocuments] // Copy the checkDocuments array
const item = {...arr[index]} // Copy the item inside the array
item.check = !item.check; // Change the value
arr[index] = item;
obj[section].checkDocuments = arr;
setDocuments(obj);
}
实际上是同一件事的另一种方法是@AsafAviv的操作方式。
功能组件中的状态更新必须是不可变的。
建议在状态内更新对象并散布每个对象以避免丢失其余属性时使用回调模式
updateDataDocument = (section, index) => {
setDocuments(prevState => ({
// spread the previous state into a new object
...prevState,
[section]: {
// also spread prevState[section] into a new object
...prevState[section],
// create a new array of checkDocuments
checkDocuments: prevState[section].checkDocuments.map((doc, i) =>
i === index
? // when we find the object we need to update,
// spread it into a new object and then update
// the check property
{ ...doc, check: !doc.check }
: doc
),
},
}))
}
嵌套的不可变更新很丑陋,最好引入一个不可变的库来为您处理,例如immer,它具有hooks version,可让您以可变的方式更新状态
import { useImmer } from 'use-immer'
export const Verificardocuments = props => {
const [documents, setDocuments] = useImmer(props.data);
const updateDataDocument = (section, index) => {
setDocuments(draft => {
const prevChecked = draft[section].checkDocuments[index].check
draft[section].checkDocuments[index].check = !prevChecked
})
}
return ...
}
documents
被突变,这就是为什么它不会触发重新渲染的原因。因此,我建议将其分配给本地副本,并在那里进行突变
updateDataDocument = (section, index) => {
const newDoc = documents
newDoc[section].checkDocuments[index].check = !newDoc[section].checkDocuments[index].check;
setDocuments(newDoc)
}
documents
被突变,这就是为什么它不会触发重新渲染的原因。因此,我建议将其分配给本地副本,并在那里进行突变
updateDataDocument = (section, index) => {
const newDoc = documents
newDoc[section].checkDocuments[index].check = !newDoc[section].checkDocuments[index].check;
setDocuments(newDoc)
}