skip to Main Content

I am recently learning the map and filter method in react native and I have a question. After finding a particular row of my array (with filter), how do I set only a particular field of that specific row?
I have

this.state = {
  post: [{ id: "0", author: "Duffy Duck", delay: "1", picture: "" }]
}
putpicture(id) {
  const picture_new = "/gggg(yyb45789986..."
  const data = this.state.post
    .filter((item) => item.author == id)
    // my error is here. How can i put picture_new const, inside post.picture?
    .map((pictures) => this.setState({ post.picture: picture_new }))
}  

Now i want setState inside map and filter for every post.
i want this output:

id:"0", author:"Duffy Duck",delay:"1", picture:"/gggg(yyb45789986..."

How can i do?

3

Answers


  1. This doesn’t 100% make sense to me – are you sure you want to set all pictures on posts by an author at once? Is the post array meant to hold multiple posts? It looks like that’s the goal based on the code, so I’ll answer that as is.

    EDIT: changed to reflect one post at a time.

    You’re close to a solution – the things you’re missing are

    1. You can use .find instead of .filter since you only want one post
    2. Since you can use .find, which returns a single item, you don’t need to .map.
    putpicture(id) {
      const picture_new = "/gggg(yyb45789986...";
      const modifiedPost = this.state.post.find((item) => item.id === id);
      modifiedPost.picture = picture_new;
      // now that you have the modified post, put it into state
      // first, get all the other (unmodified) posts
      const otherPosts = this.state.post.filter((item) => item.id !== id);
      // add the new post to the array and set state
      this.setState({ post: [...otherPosts, modifiedPost] });
    }
    

    As an aside, if you’re going to be doing this a lot, I would recommend making your state an object with IDs as the keys, instead of an array. .find and .filter loop over each array member and can do a lot of unnecessary work. If you set up your state like this:

    this.state = {
      post: {
        0: { id: "0", author: "Duffy Duck", delay: "1", picture: "" },
      }
    };    
    

    then you can modify it much more easily:

    putpicture(id) {
      const picture_new = "/gggg(yyb45789986...";
      const newPosts = {
        ...this.state.post,
        [id]: {
          ...this.state.post[id],
          picture: new_picture,
        }
      };
      
      this.setState({ post: newPosts });
    }
    

    This is much faster when dealing with large arrays.

    Login or Signup to reply.
  2. In case you can have more than one post in array and anything apart of post in you state:

    putpicture(id) {
        const picture_new = "/gggg(yyb45789986...";
        // create new array by reducing source array
        const newPost = this.state.post.reduce((res, it) => {
            // update only item(s) matching the condition
            res.push(it.author === id ? {...it, picture: picture_new} : {...it});
    
            return res;
        }, []);
    
        // use destructuring and previous state to update the state 
        this.setState(prev => {...prev, post: newPost});
    }
    
    Login or Signup to reply.
  3. It seems to me that you’re only looking to change one particular entry of your array.
    It also seems like you meant to search by id and not author.

    If that’s the case, you’ll want to use findIndex to find the correct index.
    Make a shallow copy of the array so as not to modify the original.
    Then assign a modified copy of that object to that index, again so as not to modify the original.
    Then assign the new array to the state.

    Since the updated state relies on the previous state, you should house all of this within a setState callback function. This is because state updates may be asynchronous, as outlined here: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous. In other words, this ensures you get the most up to date version of your state at the time of applying the change.

      putpicture(id) {
        const picture_new = '/gggg(yyb45789986...';
        this.setState(({ post }) => {
          // find index of item to edit
          const index = post.findIndex((item) => item.id === id);
          if (index === -1) return;
          // create shallow copy of array
          const newPost = [...post];
          // replace old object with new object
          newPost[index] = { ...post[index], picture: picture_new };
          return { post: newPost };
        });
      }
    

    Stackblitz: https://stackblitz.com/edit/react-ts-ht8hx9?file=App.tsx


    If I’ve misunderstood your intentions, please reword your question to be more clear. You use the term "row of my array", but this a 1-dimensional array, there are no rows. In the question you also mention modifying "every post", but in a comment you mention modifying only "a post".

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search