React – 有没有一种清晰的方法来更新状态中的嵌套属性?

huangapple go评论59阅读模式
英文:

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: &quot;chicago&quot;,
country: &quot;us&quot;,
data: [
{
temperature: 75,
date: &#39;2023-05-18&#39;
},
{
temperature: 60,
date: &#39;2023-05-20&#39;
}
]
}
])

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 &#39;react-native&#39;;
import { useState } from &#39;react&#39;;
const App = () =&gt;  {
const [data, setData] = useState([
{
id: 0,
name: &quot;chicago&quot;,
country: &quot;us&quot;,
data: [
{
temperature: 75,
date: &#39;2023-05-18&#39;
},
{
temperature: 60,
date: &#39;2023-05-20&#39;
}
]
}
])
const addOneDegree = (item, index, section) =&gt; {
let newItem = {...item}
let newSection = {...section}
let newData = [...data]
newItem.temperature++
newSection.data[index] = newItem
newData[section.id] = newSection
setData(newData)
}
return (
&lt;View style={styles.container}&gt;
&lt;SectionList
sections={data}
keyExtractor={(item, index) =&gt; item + index}
renderItem={({item, index, section}) =&gt; &lt;TouchableOpacity onPress={() =&gt; addOneDegree(item, index, section)}&gt;&lt;Text&gt;{item.temperature}&#176;F - {item.date}&lt;/Text&gt;&lt;/TouchableOpacity&gt;}
renderSectionHeader={({section}) =&gt;  &lt;Text&gt;{section.name} - {section.country}&lt;/Text&gt;} 
/&gt; 
&lt;/View&gt;
);
}
export default App;
const styles = StyleSheet.create({
container: {
backgroundColor: &#39;#fff&#39;,
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 &#39;react&#39;;
import {
  StyleSheet,
  Text,
  View,
  SectionList,
  TouchableOpacity,
} from &#39;react-native&#39;;

import { useImmer } from &#39;use-immer&#39;; // new import

const App = () =&gt; {
  // change to &quot;useImmer&quot;
  const [data, setData] = useImmer([
    {
      id: 0,
      name: &#39;chicago&#39;,
      country: &#39;us&#39;,
      data: [
        {
          temperature: 75,
          date: &#39;2023-05-18&#39;,
        },
        {
          temperature: 60,
          date: &#39;2023-05-20&#39;,
        },
      ],
    },
  ]);

  const addOneDegree = (item, index, section) =&gt; {
    // new setter
    setData((draft) =&gt; {
      draft[section.id].data[index].temperature++;
    });
  };

  return (
    &lt;View style={styles.container}&gt;
      &lt;SectionList
        sections={data}
        keyExtractor={(item, index) =&gt; item + index}
        renderItem={({ item, index, section }) =&gt; (
          &lt;TouchableOpacity onPress={() =&gt; addOneDegree(item, index, section)}&gt;
            &lt;Text&gt;
              {item.temperature}&#176;F - {item.date}
            &lt;/Text&gt;
          &lt;/TouchableOpacity&gt;
        )}
        renderSectionHeader={({ section }) =&gt; (
          &lt;Text&gt;
            {section.name} - {section.country}
          &lt;/Text&gt;
        )}
      /&gt;
    &lt;/View&gt;
  );
};

export default App;

const styles = StyleSheet.create({
  container: {
    backgroundColor: &#39;#fff&#39;,
    marginTop: 60,
  },
});

huangapple
  • 本文由 发表于 2023年5月22日 18:00:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305014.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定