最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - useState and changes in the props - Stack Overflow

programmeradmin13浏览0评论

I'm trying to understand what happens when you have both props and useState in one component.

I wrote little example of it which has one parent component that prints its numbers with another child component -

const MyNumbers = (props) => {
  const [numbers, setNumbers] = useState([...props.arr]);

  function changeNumbers() {
    setNumbers((nums) => [...nums.map(() => Math.floor(Math.random() * 10))]);
  }

  return (
    <div className="MyNumbers">
      <div>
        <button onClick={changeNumbers}>Chane numbers</button>
      </div>
      <div>
        {numbers.map((num, idx) => (
          <SingleNumber key={idx} num={num}></SingleNumber>
        ))}
      </div>
    </div>
  );
};
const SingleNumber = (props) => {
  const [num] = useState(props.num);
  useEffect(() => {
    console.log("useEffect called");
  });
  return <h3>The number is {num}</h3>;
};

Here is the above demo

The SingleNumber component uses useState and as you can see clicking on the "Change numbers" action doesn't change the values in the children component.

But when I wrote almost the same code but now SingleNumber doesn't use useState then clicking on the "Change numbers" changes all the values in the children component (like in this demo).

Is it correct to say that a function component with a useState renders once and then only changed if the state changed but not if the props changed ?

I'm trying to understand what happens when you have both props and useState in one component.

I wrote little example of it which has one parent component that prints its numbers with another child component -

const MyNumbers = (props) => {
  const [numbers, setNumbers] = useState([...props.arr]);

  function changeNumbers() {
    setNumbers((nums) => [...nums.map(() => Math.floor(Math.random() * 10))]);
  }

  return (
    <div className="MyNumbers">
      <div>
        <button onClick={changeNumbers}>Chane numbers</button>
      </div>
      <div>
        {numbers.map((num, idx) => (
          <SingleNumber key={idx} num={num}></SingleNumber>
        ))}
      </div>
    </div>
  );
};
const SingleNumber = (props) => {
  const [num] = useState(props.num);
  useEffect(() => {
    console.log("useEffect called");
  });
  return <h3>The number is {num}</h3>;
};

Here is the above demo

The SingleNumber component uses useState and as you can see clicking on the "Change numbers" action doesn't change the values in the children component.

But when I wrote almost the same code but now SingleNumber doesn't use useState then clicking on the "Change numbers" changes all the values in the children component (like in this demo).

Is it correct to say that a function component with a useState renders once and then only changed if the state changed but not if the props changed ?

Share Improve this question edited Dec 17, 2020 at 8:34 Dennis Vash 53.9k11 gold badges115 silver badges132 bronze badges asked Dec 17, 2020 at 8:12 URL87URL87 11k36 gold badges111 silver badges177 bronze badges 1
  • 1 The component re-renders each time. But you have essentially cached the value in the local state and output that all the time. The value you pass to useState is only used for when the component is mounted (first time only). – Gabriele Petrioli Commented Dec 17, 2020 at 10:18
Add a comment  | 

4 Answers 4

Reset to default 5

OFC the component "rerenders" when the props change, the useEffect hook in SingleNumber is showing you that the "render phase" is run each time the props change.... effects are run each time the component is rendered.

const SingleNumber = (props) => {
  const [num] = useState(props.num);
  useEffect(() => {
    console.log("useEffect called"); // <-- logged each time the component renders
  });
  return <h3>The number is {num}</h3>;
};

If you added a dependency on props.num and updated the local state (don't actually do this, it's an anti-pattern in react!), you'll see the UI again update each time the props update.

To answer your queston:

Is it correct to say that a function component with a useState renders once and then only changed if the state changed but not if the props changed?

No, this is not technically correct to say if "render" to you means strictly react rendered the component to compute a diff, react components rerender when state or props update. Yes, if "render" more generally means you visually see the UI update.

When you call useState it returns an array with two values in it:

  1. The current value of that bit of the state
  2. A function to update the state

If there is no current value when it sets the state to the default value and returns that.

(The default value is the argument you pass to useState).


If you change the values of props in your example, then the component rerenders.

useState returns the current value of that bit of the state. The state has a value, so it doesn't do anything with the argument you pass to useState. It doesn't matter that that value has changed.

Since nothing else has changed in the output, the rerendered component doesn't update the DOM.

Is it correct to say that a function component with a useState renders once and then only changed if the state changed but not if the props changed?

No, it does rerender but doesn't commit the changes.

When parent component MyNumbers re-renders by clicking changeNumbers, by default (unless React.memo used) all its children components (like SingleNumber) will be re-render.

Now when SingleNumber rerenders, notice useState docs.

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).

You initial the state useState(props.num) but it can only be changed by calling the setter function, therefore the state num won't change because you never calling the setter.

But it will rerender on parent render as mentioned above (notice the useEffect logs).

You don't need to use useState in SingleNumber.

because useState called only once when it rendered.

const SingleNumber = (props) => {
  // const [num] = useState(props.num);
  // useEffect(() => {
  //   console.log("useEffect called");
  // });
  return <h3>The number is {props.num}</h3>;
};

if you want to use useState, you can use like this.

const SingleNumber = (props) => {
   const [num, setNum] = useState(props.num);
   useEffect(() => {
     console.log("useEffect called");
     setNum(props.num);

   }, [props.num]);
  return <h3>The number is {num}</h3>;
};
发布评论

评论列表(0)

  1. 暂无评论