skip to Main Content

I am new to React and I have this simple code and I got two questions:

import { useState, useEffect } from 'react';

const UpdateArticle = () => {
  let filteredArticle;
  const id = 2;
  const [theArticle, setTheArticle] = useState({});

  const testArticles = [
    {
      id: 1,
      title: 'Maxaan qabtaa?',
      body: 'Wax daran bay ku hadlayaan kuwa halkaan ila jooga.',
      writer: 'Jama',
    },
    {
      id: 2,
      title: 'Why django?',
      body: 'Simple: it is very simple.',
      writer: 'Dennis',
    },
  ];

  const updateArticle = () => {
    filteredArticle = testArticles.find((article) => article.id === id);
    setTheArticle(filteredArticle);
  };
  // console.log("Test");
  useEffect(() => {
    updateArticle();
    console.log('Test');
    console.log(filteredArticle);
    console.log(theArticle);
  }, [id]);

  return (
    <div className="article update">
      <h1>{theArticle.title}</h1>
    </div>
  );
};
  1. Why is the setTheArticle method is not setting the theArticle instantly? The console.log in the useEffect gives an empty object even though the filteredArticle above it has a correct value.

  2. the console does everything twice. This is the case even if I put one outside useEffect and outside the updateArticle function. for example, for the above case it gives something like this:

Test
{id: 2, title: "Why django?", body: "Simple: it is very simple.", writer: "Dennis"}
{} (empty???)
Test
{id: 2, title: "Why django?", body: "Simple: it is very simple.", writer: "Dennis"}
{} (empty???)

The question is why?

I even suspected it is my configuration and went to stackblitz. The same thing. and also I am NOT calling the component twice.

2

Answers


  1. Answers to your questions:

    1. setState will not fire immediately and if you want to get the new state you should listen to it in another useEffect with this state as its dependency.
    2. Firing the useEffect twice is because of the StrictMode.
      You can read about that in the React docs.

    Some advice base on your example code:

    1. Try to use callback in setState for changing the previous state:
    const updateArticle = () => {
        setTheArticle(prev => prev.find((article) => article.id === id));
      };
    
    1. Put all used data in a useEffect in its dependencies array.
    2. Read docs of the react.dev carefully to avoid unexpected behavior.
    Login or Signup to reply.
  2. useState is an asynchronous hook and it doesn’t change the state immediately, it has to wait for the component to re-render. useRef is a synchronous hook that updates the state immediately and persists its value through the component’s lifecycle, but it doesn’t trigger a re-render.

    To use callback in the useState hook, we need to use the useEffect hook that triggers after state update and call the function after that. We need to pass state in the useEffect Dependency Array. useEffect is triggered when the state updates and then calls the inside function immediately.

    you can log the state inside JSX to see actual value of the state when component has been mounted (componentDidMount)

    read the following link
    javascript plainenglish, useState

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