Thomas Segato
Thomas Segato

Reputation: 5223

Setting values in a child component in react

In following scenario I have a very simple child component (arrow component) that acts like a counter. The counter can increment a simple value. What if the parent wants to set that counter to x? The obvious answer would be just have a parameter that you set to x. But as my variable in the parent component is a hook, it would be read only. Would you then have to add a parameter for both the getter and setter variable on the child? And then the child would work on those two variables? Or what is best practice here? Or is there some way to transfer the complete hook to the child? It is really not beautiful that you must add two parameters to the child in my world.

const App = props => {
  const resetChildCounter = () => {
    alert("what to do here");
  };

  return (
    <div className="App">
      <Child />
      <button onClick={resetChildCounter}>
        Reset child counter from parent
      </button>
      <button onClick={resetChildCounter}>Set child counter to 5</button>
    </div>
  );
};

const Child = props => {
  const [counter, setCounter] = useState(0);

  return (
    <div>
      <span>Counter is: {counter}</span>
      <button
        onClick={() => {
          setCounter(counter + 1);
        }}
      >
        Increment
      </button>
    </div>
  );
};

Edit Call child

Upvotes: 1

Views: 122

Answers (2)

Dennis Vash
Dennis Vash

Reputation: 53874

The Child component acts like a "hybrid" component, it acts as a controlled component and an uncontrolled component.

A simple implementation of a hybrid component looks like this:

const NOOP = () => {}

const Child = ({ initial = 0, onChange = NOOP }) => {
  const [counter, setCounter] = useState(initial);

  useEffect(() => {
    setCounter(initial);
  }, [initial]);

  useEffect(() => {
    onChange(counter);
  }, [onChange, counter]);

  return (
    <div>
      <span>Counter is: {counter}</span>
      <button onClick={() => setCounter(p => p + 1)}>Increment</button>
    </div>
  );
};

export default Child;

Edit Call child

In this case, as stated by the OP:

I would like to make a self-maintained child component with much more stuff than a simple button.

You get a stand-alone component with a controlled feature.

Upvotes: 2

technophyle
technophyle

Reputation: 9118

You're correct.

If you need to set it from the parent, you need to store it as a state of the parent, not the child. And if you need to use it on the child, you need to pass it down to the child. Finally, if you need to set it from the child as well, you don't do it directly, but through a setter prop passed down from the parent.

It is really not beautiful that you must add two parameters to the child in my world.

If you have a state in either parent or child, and then if it's possible for you to mutate it from both sides, that is more ugly. It will break the philosophy of React.

Upvotes: 0

Related Questions