1

I use react hooks. If the props are changed what ways are there to get the initial value? I want to avoid the anti-pattern effect.

Situation 1: Before building a DOM.

As I understand it, for these purposes fit useMemo.if there is other options you can their show.

Situation 2: After the DOM

And in this variant useLayoutEffect, useEffect.if there is other options you can their show.

import React, { useState, useMemo, useLayoutEffect, useEffect } from "react";
import ReactDOM from "react-dom";

import "./styles.css";
const X = () => {
  const [x, setX] = useState(0);
  return (
    <div>
      <div>
        <Y x={x} />
      </div>
      <div onClick={() => setX(x + 1)}>{"go"}</div>
    </div>
  );
};

function Y({ x }) {
  const [y, setY] = useState(x);

  /*useMemo(() => {
    console.log("");
    setY(x);
  }, [x]);*/
  /*useEffect(() => {
    console.log("");
    setY(x);
  }, [x]);*/
  /*useLayoutEffect(() => {
    console.log("");
    setY(x);
  }, [x]);*/
  console.log(y);
  return <div className="App">{console.log(y, "DOM")}</div>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<X />, rootElement);

I do not think it is good practice to use all these hooks. but I see no other solution. Maybe there is a third option without using hooks?

Dale K
  • 25,246
  • 15
  • 42
  • 71
Edgar
  • 6,022
  • 8
  • 33
  • 66

2 Answers2

1

In your example, do you need to store state inside of Y? Why not directly refer to the prop x?

If you are looking to update the y state in Y when the prop x changes, you can use useEffect with a dependency on x.

useEffect(() => {
  setY(x);
}, [x]);

You would not use useMemo in this case since it you are not computing and returning a value.

jhsu
  • 333
  • 1
  • 7
  • 2
    useEffect fits 2 situation,for 1 situation? – Edgar Jul 18 '19 at 22:04
  • @Squanchy i'm not sure i understand the purpose, but instead of using a hook, you could simply check that if x and y are different, use the y value `const renderValue = x !== y ? y : x;` inside of your `Y` component. – jhsu Jul 19 '19 at 23:04
0

What do you mean with "get the initial value" ? If you just want to store the first value ever passed to this component you could use useRef()

function Y ({ x }) {
  const initial = useRef(x)
  const y = initial.current

  return <div>the inital value was {y} and the current value is {x}</div>
}

If you want to get the previous value you could do that like this:

function Y ({ x }) {
  const previous = useRef(null)

  const y = previous.current
  // A component coud rerender all the time
  // so only change the previous value when x changes
  useEffect(() => { previous.current = x }, [x])

  return <div>the previous value was {y} and the current value is {x}</div>
}
errnesto
  • 822
  • 5
  • 15
  • 6
    I want to do something like this: `const [y, setY] = useState (x);`, [But, it is considered anti-pattern](https://stackoverflow.com/questions/40063468/react-component-initialize-state-from-props) . – Edgar Jul 18 '19 at 22:36
  • there's nothing wrong with doing it that way, but you'd just have to be aware that changing `x` won't affect state. only the initial value of x. – jhsu Jul 19 '19 at 23:11
  • @jhsu How do you know? – Edgar Aug 06 '19 at 10:10
  • @Squanchy "The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded." -- https://reactjs.org/docs/hooks-reference.html#lazy-initial-state – jhsu Aug 07 '19 at 16:01