0

I am trying to set an object using set state, however nothing is happening.

I am initializing the blog object to an almost empty object, then I am setting it to a new object via setBlog.

Note that when logging to the console, I can see the foundBlog object so the problem isn't there. The problem is when logging the blog object after setBlog I am seeing the initial object, so setBlog didn't do anything.

My question is this: what is the proper way to use setBlog in this case?

import React, { useEffect, useState } from 'react';
import { RouteComponentProps, withRouter } from 'react-router';

import Blogs from '../../mock-data/draftBlogs.json';
import BlogCreation, { IBlogCreationProps } from './create-edit-blog/BlogCreation';

interface IBlogPageProps {

}

const blogArr = Blogs.blogs;

const BlogPage: React.FunctionComponent<IBlogPageProps & RouteComponentProps<any>> = (props) => {

  const [blog, setBlog] = useState<IBlogCreationProps>({
    id: 4,
    title: "",
    content: "",
    description: "",
    publisher: "",
    published: false
  });
  
  useEffect(() => {
    let number: number = props.match.params.number;
   
    const foundBlog = (blogArr.find(({id}) => id == number)) as IBlogCreationProps;
    console.log("foundBlog", foundBlog); // logs the expected result
    // code below is supposed to set the object to the new object, but it's not working
    setBlog({...blog,
      id: foundBlog.id,
      title: foundBlog.title,
      content: foundBlog.content,
      description: foundBlog.description,
      publisher: foundBlog.publisher,
      published: foundBlog.published}
      );
    console.log("blog", blog); // logs the initial object
  }, [props])
  return (
    <BlogCreation
      id={blog.id}
      title={blog.title}
      content={blog.content}
      description={blog.description}
      publisher={blog.publisher}
      published={blog.published}
    />
  );
};

export default withRouter(BlogPage);

Edit:

It turns out this is a problem related to the dependency array, changing the dependencies fixed the initial logging problem (not seeing the correct object), but it added other problems, I can see two logs instead of one. Anyway my main problem which is rendering a component with the correct props is not solved.

Nameless
  • 41
  • 1
  • 3
  • Hi look this [post](https://stackoverflow.com/questions/53715465/can-i-set-state-inside-a-useeffect-hook) try to setState like this in useEffect(() => { setState(state => {...state})},[]) – Daphaz Apr 28 '21 at 13:18

1 Answers1

0

Your code seems to work. The reason why you don't see the change with a console.log is that setState is asynchronous. This function doesn't update the value, it tells React you want to update it, and React will do it by itself very soon after. The consequence is that the state is not reassigned immediately, and your code logs the state before it is updated.

However you can pass a callback as second argument to setState which will be called right after the update is done: setState(newValue, callback).

setBlog({...blog,
      id: foundBlog.id,
      title: foundBlog.title,
      content: foundBlog.content,
      description: foundBlog.description,
      publisher: foundBlog.publisher,
      published: foundBlog.published
}, () => console.log("blog", blog)); // this is called after the state
                                     // is effectively updated
papillon
  • 1,807
  • 2
  • 19
  • 39