英文:
React - Is there an clean way to update nested properties in a state?
问题
以下是您要翻译的内容:
"I'm struggling to update nested properties in a state, especially when arrays are involved.
I have data like this, and trying to update the temperature when the user touches the line:
const [data, setData] = useState([
{
id: 0,
name: "chicago",
country: "us",
data: [
{
temperature: 75,
date: '2023-05-18'
},
{
temperature: 60,
date: '2023-05-20'
}
]
}
])
I managed to make it work, but I feel like my code is a bit dirty. Is there a better way to do this?"
import { StyleSheet, Text, View, SectionList, TouchableOpacity } from 'react-native';
import { useState } from 'react';
const App = () => {
const [data, setData] = useState([
{
id: 0,
name: "chicago",
country: "us",
data: [
{
temperature: 75,
date: '2023-05-18'
},
{
temperature: 60,
date: '2023-05-20'
}
]
}
])
const addOneDegree = (item, index, section) => {
let newItem = {...item}
let newSection = {...section}
let newData = [...data]
newItem.temperature++
newSection.data[index] = newItem
newData[section.id] = newSection
setData(newData)
}
return (
<View style={styles.container}>
<SectionList
sections={data}
keyExtractor={(item, index) => item + index}
renderItem={({item, index, section}) => <TouchableOpacity onPress={() => addOneDegree(item, index, section)}><Text>{item.temperature}°F - {item.date}</Text></TouchableOpacity>}
renderSectionHeader={({section}) => <Text>{section.name} - {section.country}</Text>}
/>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
marginTop: 60
},
});
英文:
I'm struggling to update nested properties in a state, especially when arrays are involved.
I have data like this, adn trying to update the temperature when user touches the line:
const [data, setData] = useState([
{
id: 0,
name: "chicago",
country: "us",
data: [
{
temperature: 75,
date: '2023-05-18'
},
{
temperature: 60,
date: '2023-05-20'
}
]
}
])
I managed to make it work but i feel like my code is a bit dirty, is there a better way to do this?
import { StyleSheet, Text, View, SectionList, TouchableOpacity } from 'react-native';
import { useState } from 'react';
const App = () => {
const [data, setData] = useState([
{
id: 0,
name: "chicago",
country: "us",
data: [
{
temperature: 75,
date: '2023-05-18'
},
{
temperature: 60,
date: '2023-05-20'
}
]
}
])
const addOneDegree = (item, index, section) => {
let newItem = {...item}
let newSection = {...section}
let newData = [...data]
newItem.temperature++
newSection.data[index] = newItem
newData[section.id] = newSection
setData(newData)
}
return (
<View style={styles.container}>
<SectionList
sections={data}
keyExtractor={(item, index) => item + index}
renderItem={({item, index, section}) => <TouchableOpacity onPress={() => addOneDegree(item, index, section)}><Text>{item.temperature}°F - {item.date}</Text></TouchableOpacity>}
renderSectionHeader={({section}) => <Text>{section.name} - {section.country}</Text>}
/>
</View>
);
}
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
marginTop: 60
},
});
答案1
得分: 1
以下是您要翻译的内容:
尝试使用 Immer https://immerjs.github.io/immer/
安装:
npm install immer use-immer
代码:
import { useState } from 'react';
import {
StyleSheet,
Text,
View,
SectionList,
TouchableOpacity,
} from 'react-native';
import { useImmer } from 'use-immer'; // 新的导入
const App = () => {
// 更改为 "useImmer"
const [data, setData] = useImmer([
{
id: 0,
name: '芝加哥',
country: '美国',
data: [
{
temperature: 75,
date: '2023-05-18',
},
{
temperature: 60,
date: '2023-05-20',
},
],
},
]);
const addOneDegree = (item, index, section) => {
// 新的 setter
setData((draft) => {
draft[section.id].data[index].temperature++;
});
};
return (
<View style={styles.container}>
<SectionList
sections={data}
keyExtractor={(item, index) => item + index}
renderItem={({ item, index, section }) => (
<TouchableOpacity onPress={() => addOneDegree(item, index, section)}>
<Text>
{item.temperature}°F - {item.date}
</Text>
</TouchableOpacity>
)}
renderSectionHeader={({ section }) => (
<Text>
{section.name} - {section.country}
</Text>
)}
/>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
marginTop: 60,
},
});
希望这能帮助到您。
英文:
Try to use Immer https://immerjs.github.io/immer/
Installation:
npm install immer use-immer
Code:
import { useState } from 'react';
import {
StyleSheet,
Text,
View,
SectionList,
TouchableOpacity,
} from 'react-native';
import { useImmer } from 'use-immer'; // new import
const App = () => {
// change to "useImmer"
const [data, setData] = useImmer([
{
id: 0,
name: 'chicago',
country: 'us',
data: [
{
temperature: 75,
date: '2023-05-18',
},
{
temperature: 60,
date: '2023-05-20',
},
],
},
]);
const addOneDegree = (item, index, section) => {
// new setter
setData((draft) => {
draft[section.id].data[index].temperature++;
});
};
return (
<View style={styles.container}>
<SectionList
sections={data}
keyExtractor={(item, index) => item + index}
renderItem={({ item, index, section }) => (
<TouchableOpacity onPress={() => addOneDegree(item, index, section)}>
<Text>
{item.temperature}°F - {item.date}
</Text>
</TouchableOpacity>
)}
renderSectionHeader={({ section }) => (
<Text>
{section.name} - {section.country}
</Text>
)}
/>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
marginTop: 60,
},
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论