I am trying to change the properties of objects inside of an object and trying to add new properties to these objects but keeping the old values.
I can't find out how to get the right nested object by index, not id because the id can be different from the .map index.
This is what I got so far, the Object names are for testing purposes only and maybe the "updateNestedObject" can be run in the parent?
Thank you in advance and sorry if this is a noob question.
Neval
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet, Button, Alert } from 'react-native';
function ObjectScreen() {
const [state, setState] = useState({
id: 1,
name: 'Test Object',
nested: [
{
id: 1,
title: 'Object 1',
},
{
id: 2,
title: 'Object 1',
}
]
});
function editNested({nestedObject, index, setState}) {
const updateNestedObject = () => {
setState(prevState => ({
nested: [
...prevState.nested,
[prevState.nested[index].comment]: 'Test Comment',
},
}));
}
return (
<View>
<Text>{object.title}</Text>
<TextInput
style={styles.input}
name="comment"
onChangeText={updateNestedObject}
/>
</View>
);
}
return (
<>
<Text>{state.name}</Text>
{ state.nested.map((nestedObject, key)=>{
return (
<editNested key={key} index={key} object={object} nestedObject={nestedObject}/>
)
})}
</>
)
}
const styles = StyleSheet.create({
container: {},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
});
export default ObjectScreen;
CodePudding user response:
There were few issues:
JSX component name
editNested
should start with a capital letter.And
editNested
component should be on its own function, should not define inside another component which caused yourTextInput
to lose focus after each render cycle.The
setState
call should be changed like below:
const updateNestedObject = (text) => {
setState((prevState) => ({
...prevState,
nested: prevState.nested.map((item) =>
item.id === nestedObject.id ? { ...item, value: text } : item
)
}));
};
Try the code below:
import React, { useState } from "react";
import { View, TextInput, Text, StyleSheet, Button, Alert } from "react-native";
function EditNested({ nestedObject, setState }) {
const updateNestedObject = (text) => {
setState((prevState) => ({
...prevState,
nested: prevState.nested.map((item) =>
item.id === nestedObject.id ? { ...item, value: text } : item
)
}));
};
return (
<View>
<Text>{nestedObject.title}</Text>
<TextInput
style={styles.input}
onChangeText={updateNestedObject}
value={nestedObject.value}
/>
</View>
);
}
function ObjectScreen() {
const [state, setState] = useState({
id: 1,
name: "Test Object",
nested: [
{
id: 1,
title: "Object 1",
value: ""
},
{
id: 2,
title: "Object 1",
value: ""
}
]
});
console.log(state);
return (
<>
<Text>{state.name}</Text>
{state.nested.map((nestedObject, key) => {
return (
<EditNested
key={key}
nestedObject={nestedObject}
setState={setState}
/>
);
})}
</>
);
}
const styles = StyleSheet.create({
container: {},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10
}
});
export default ObjectScreen;
Working Demo
CodePudding user response:
As per que you can update nested array with below method
const updateNestedObject = (values, item, index) => {
console.log('values', values);
const tempMainObj = state;
const tempArr = state.nested;
tempArr[index].value = values;
const updatedObj = { ...tempMainObj, nested: tempArr };
setState(updatedObj);
};
Full Example
import React, { useState } from 'react';
import { View, TextInput, Text, StyleSheet, Button, Alert } from 'react-native';
function ObjectScreen() {
const [state, setState] = useState({
id: 1,
name: 'Test Object',
nested: [
{
id: 1,
title: 'Object 1',
value: '',
},
{
id: 2,
title: 'Object 1',
value: '',
},
],
});
const updateNestedObject = (values, item, index) => {
console.log('values', values);
const tempMainObj = state;
const tempArr = state.nested;
tempArr[index].value = values;
const updatedObj = { ...tempMainObj, nested: tempArr };
setState(updatedObj);
};
return (
<>
<Text style={{ marginTop: 50 }}>{state.name}</Text>
{state.nested.map((item, index) => {
return (
<>
<Text>{item.title}</Text>
<TextInput
value={item?.value}
style={styles.input}
name="comment"
onChangeText={(values) => updateNestedObject(values, item, index)}
/>
</>
);
})}
</>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 50,
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
},
});
export default ObjectScreen;
Snack expo: Live Example