Correct way to setState a property of nested object with array properties












2















Good day! I have a nested state with array children, and I would like to know the correct and best way to setState.



Here's a sample state object.
EDITED, Forgot to mention that lists is an array of objects.



this.state = {
lists:
[{

name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}]
}
}


I use this to setState of the permission's properties but the state is not updated.



this.setState({
...this.state, lists: {
...this.state.lists, key: [
...this.state.lists.key, permission : {
...this.state.lists.key.permission,
canRead: !this.state.lists.key.permission.canRead
}
]
}
});


I hope you can help me. Thanks!










share|improve this question

























  • In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

    – Tazo leladze
    Nov 15 '18 at 19:03
















2















Good day! I have a nested state with array children, and I would like to know the correct and best way to setState.



Here's a sample state object.
EDITED, Forgot to mention that lists is an array of objects.



this.state = {
lists:
[{

name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}]
}
}


I use this to setState of the permission's properties but the state is not updated.



this.setState({
...this.state, lists: {
...this.state.lists, key: [
...this.state.lists.key, permission : {
...this.state.lists.key.permission,
canRead: !this.state.lists.key.permission.canRead
}
]
}
});


I hope you can help me. Thanks!










share|improve this question

























  • In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

    – Tazo leladze
    Nov 15 '18 at 19:03














2












2








2


1






Good day! I have a nested state with array children, and I would like to know the correct and best way to setState.



Here's a sample state object.
EDITED, Forgot to mention that lists is an array of objects.



this.state = {
lists:
[{

name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}]
}
}


I use this to setState of the permission's properties but the state is not updated.



this.setState({
...this.state, lists: {
...this.state.lists, key: [
...this.state.lists.key, permission : {
...this.state.lists.key.permission,
canRead: !this.state.lists.key.permission.canRead
}
]
}
});


I hope you can help me. Thanks!










share|improve this question
















Good day! I have a nested state with array children, and I would like to know the correct and best way to setState.



Here's a sample state object.
EDITED, Forgot to mention that lists is an array of objects.



this.state = {
lists:
[{

name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}]
}
}


I use this to setState of the permission's properties but the state is not updated.



this.setState({
...this.state, lists: {
...this.state.lists, key: [
...this.state.lists.key, permission : {
...this.state.lists.key.permission,
canRead: !this.state.lists.key.permission.canRead
}
]
}
});


I hope you can help me. Thanks!







javascript reactjs babeljs jsx






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 11:44







alvirbismonte

















asked Nov 15 '18 at 18:40









alvirbismontealvirbismonte

8213




8213













  • In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

    – Tazo leladze
    Nov 15 '18 at 19:03



















  • In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

    – Tazo leladze
    Nov 15 '18 at 19:03

















In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

– Tazo leladze
Nov 15 '18 at 19:03





In setState you are using object {...this.state.list} and not [...this.state.lists] this is problem.

– Tazo leladze
Nov 15 '18 at 19:03












2 Answers
2






active

oldest

votes


















2














You can create a copy of the lists array, and then replace the object of the index you want to change with a copy of that same object but where you change the permission.



Example






class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>








share|improve this answer



















  • 2





    Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

    – alvirbismonte
    Nov 16 '18 at 15:47






  • 2





    @alvirbismonte Great! You're welcome.

    – Tholle
    Nov 16 '18 at 15:55






  • 1





    I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

    – Waterlink
    Nov 17 '18 at 7:58











  • @Waterlink Yeah, that would work just as well.

    – Tholle
    Nov 17 '18 at 9:47



















1














The way to change a specific element of the array with setState is to copy all items of array as they are without changing, except for the target item, this can be done with .map and if statement:



export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {
lists: [
{
name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
}
}

invertCanRead(targetId) {
this.setState({
...this.state,
lists: this.state.lists.map(list => {
if (list.id === targetId) {
// that is the one we want to modify, so let's return
// modified version:
return {
...list,
permission: {
...list.permission,
canRead: !list.permission.canRead
}
}
} else {
// else return list as is without changes because
// it's not the one we want to modify, so just copy it:
return list;
}
})
})
}

render() {
return <div>
{JSON.stringify(this.state)};
<button onClick={() => this.invertCanRead(15)}></button>
</div>
}
}





share|improve this answer



















  • 1





    Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

    – alvirbismonte
    Nov 16 '18 at 15:48













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53325985%2fcorrect-way-to-setstate-a-property-of-nested-object-with-array-properties%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














You can create a copy of the lists array, and then replace the object of the index you want to change with a copy of that same object but where you change the permission.



Example






class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>








share|improve this answer



















  • 2





    Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

    – alvirbismonte
    Nov 16 '18 at 15:47






  • 2





    @alvirbismonte Great! You're welcome.

    – Tholle
    Nov 16 '18 at 15:55






  • 1





    I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

    – Waterlink
    Nov 17 '18 at 7:58











  • @Waterlink Yeah, that would work just as well.

    – Tholle
    Nov 17 '18 at 9:47
















2














You can create a copy of the lists array, and then replace the object of the index you want to change with a copy of that same object but where you change the permission.



Example






class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>








share|improve this answer



















  • 2





    Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

    – alvirbismonte
    Nov 16 '18 at 15:47






  • 2





    @alvirbismonte Great! You're welcome.

    – Tholle
    Nov 16 '18 at 15:55






  • 1





    I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

    – Waterlink
    Nov 17 '18 at 7:58











  • @Waterlink Yeah, that would work just as well.

    – Tholle
    Nov 17 '18 at 9:47














2












2








2







You can create a copy of the lists array, and then replace the object of the index you want to change with a copy of that same object but where you change the permission.



Example






class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>








share|improve this answer













You can create a copy of the lists array, and then replace the object of the index you want to change with a copy of that same object but where you change the permission.



Example






class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>








class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>





class App extends React.Component {
state = {
lists: [
{
name: "sampleList",
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
};

updateList = (index, canRead, canWrite) => {
this.setState(prevState => {
const lists = [...prevState.lists];
lists[index] = { ...lists[index], permission: { canRead, canWrite } };
return { lists };
});
};

render() {
return (
<div>
<button onClick={() => this.updateList(0, false, true)}>
Update state
</button>
<div>{JSON.stringify(this.state)}</div>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 15 '18 at 18:51









TholleTholle

40.3k54567




40.3k54567








  • 2





    Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

    – alvirbismonte
    Nov 16 '18 at 15:47






  • 2





    @alvirbismonte Great! You're welcome.

    – Tholle
    Nov 16 '18 at 15:55






  • 1





    I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

    – Waterlink
    Nov 17 '18 at 7:58











  • @Waterlink Yeah, that would work just as well.

    – Tholle
    Nov 17 '18 at 9:47














  • 2





    Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

    – alvirbismonte
    Nov 16 '18 at 15:47






  • 2





    @alvirbismonte Great! You're welcome.

    – Tholle
    Nov 16 '18 at 15:55






  • 1





    I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

    – Waterlink
    Nov 17 '18 at 7:58











  • @Waterlink Yeah, that would work just as well.

    – Tholle
    Nov 17 '18 at 9:47








2




2





Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

– alvirbismonte
Nov 16 '18 at 15:47





Hi @Tholle, thank you for your answer. This worked for me though I've made some updates on it to satisfy my goal. Thank you again.

– alvirbismonte
Nov 16 '18 at 15:47




2




2





@alvirbismonte Great! You're welcome.

– Tholle
Nov 16 '18 at 15:55





@alvirbismonte Great! You're welcome.

– Tholle
Nov 16 '18 at 15:55




1




1





I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

– Waterlink
Nov 17 '18 at 7:58





I wonder, what if you don’t know the index, and instead, you have an “id.” Would you use findIndex first?

– Waterlink
Nov 17 '18 at 7:58













@Waterlink Yeah, that would work just as well.

– Tholle
Nov 17 '18 at 9:47





@Waterlink Yeah, that would work just as well.

– Tholle
Nov 17 '18 at 9:47













1














The way to change a specific element of the array with setState is to copy all items of array as they are without changing, except for the target item, this can be done with .map and if statement:



export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {
lists: [
{
name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
}
}

invertCanRead(targetId) {
this.setState({
...this.state,
lists: this.state.lists.map(list => {
if (list.id === targetId) {
// that is the one we want to modify, so let's return
// modified version:
return {
...list,
permission: {
...list.permission,
canRead: !list.permission.canRead
}
}
} else {
// else return list as is without changes because
// it's not the one we want to modify, so just copy it:
return list;
}
})
})
}

render() {
return <div>
{JSON.stringify(this.state)};
<button onClick={() => this.invertCanRead(15)}></button>
</div>
}
}





share|improve this answer



















  • 1





    Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

    – alvirbismonte
    Nov 16 '18 at 15:48


















1














The way to change a specific element of the array with setState is to copy all items of array as they are without changing, except for the target item, this can be done with .map and if statement:



export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {
lists: [
{
name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
}
}

invertCanRead(targetId) {
this.setState({
...this.state,
lists: this.state.lists.map(list => {
if (list.id === targetId) {
// that is the one we want to modify, so let's return
// modified version:
return {
...list,
permission: {
...list.permission,
canRead: !list.permission.canRead
}
}
} else {
// else return list as is without changes because
// it's not the one we want to modify, so just copy it:
return list;
}
})
})
}

render() {
return <div>
{JSON.stringify(this.state)};
<button onClick={() => this.invertCanRead(15)}></button>
</div>
}
}





share|improve this answer



















  • 1





    Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

    – alvirbismonte
    Nov 16 '18 at 15:48
















1












1








1







The way to change a specific element of the array with setState is to copy all items of array as they are without changing, except for the target item, this can be done with .map and if statement:



export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {
lists: [
{
name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
}
}

invertCanRead(targetId) {
this.setState({
...this.state,
lists: this.state.lists.map(list => {
if (list.id === targetId) {
// that is the one we want to modify, so let's return
// modified version:
return {
...list,
permission: {
...list.permission,
canRead: !list.permission.canRead
}
}
} else {
// else return list as is without changes because
// it's not the one we want to modify, so just copy it:
return list;
}
})
})
}

render() {
return <div>
{JSON.stringify(this.state)};
<button onClick={() => this.invertCanRead(15)}></button>
</div>
}
}





share|improve this answer













The way to change a specific element of the array with setState is to copy all items of array as they are without changing, except for the target item, this can be done with .map and if statement:



export default class App extends React.Component {
constructor(props) {
super(props);

this.state = {
lists: [
{
name: 'sampleList',
id: 15,
permission: {
canRead: true,
canWrite: false
}
}
]
}
}

invertCanRead(targetId) {
this.setState({
...this.state,
lists: this.state.lists.map(list => {
if (list.id === targetId) {
// that is the one we want to modify, so let's return
// modified version:
return {
...list,
permission: {
...list.permission,
canRead: !list.permission.canRead
}
}
} else {
// else return list as is without changes because
// it's not the one we want to modify, so just copy it:
return list;
}
})
})
}

render() {
return <div>
{JSON.stringify(this.state)};
<button onClick={() => this.invertCanRead(15)}></button>
</div>
}
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 15 '18 at 18:57









ilonacodesilonacodes

445




445








  • 1





    Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

    – alvirbismonte
    Nov 16 '18 at 15:48
















  • 1





    Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

    – alvirbismonte
    Nov 16 '18 at 15:48










1




1





Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

– alvirbismonte
Nov 16 '18 at 15:48







Hi @ilonacodes, the first answer is cleaner for me. Thank you for the effort still, it did give me ideas.

– alvirbismonte
Nov 16 '18 at 15:48




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53325985%2fcorrect-way-to-setstate-a-property-of-nested-object-with-array-properties%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine