3

I am building an application with React where two components should be able to change state of each other:

Component A -> Component B

Component B -> Component A

The Component A is a set of buttons and the Component B is an input element.

I managed to make it work only in one way, A -> B or just B -> A, but can't make it work both. It works partly with use of useEffect hook, but with bugs and this is really stupid idea, I think.

I have read a lot that React don't work this way, but is there any roundabouts how it is possible to make it work? I really need this 2-way data binding for my application.

Thanks for any help!

The state for buttons is located in digits variable from custom context hook (useStateContext) as an array.

import { useStateContext } from "components/StateProvider/Context"; 
import { useState, useEffect } from "react";

import { baseConvert } from "utility/baseConvert";

const NumberInput = () => {

  const [ { digits, baseIn, baseOut }, dispatch ] = useStateContext();

  const convertedValue = baseConvert({
    digits,
    baseIn,
    baseOut
  });

  const [ inputValue, setInputValue ] = useState(convertedValue);

  /* useEffect(() => {
    setInputValue(convertedValue)
  }, [ digits, baseIn, baseOut ]) */

  const regex = /^[A-Z\d]+$/;

  const handleInput = ({ target: { value }}) => {
    if (value === "") setInputValue(0);

    console.log(value);

    if (regex.test(value)) {
      setInputValue(value);
      dispatch({
        type: "setDigits",
        digits: baseConvert({
          digits: value.split("").map(Number),
          baseIn: baseOut,
          baseOut: baseIn
        })
      })
    }    
  };

  return (
    <input type="text" onChange={handleInput} value={inputValue} />
  );
};

export default NumberInput;
Eric Rovell
  • 393
  • 1
  • 6
  • 15

2 Answers2

8

Components should not directly manipulate the state of other components. If you need to have shared data, bring the state to a parent component and pass callbacks to the children that can change the state.

For example:

function ParentComponent() {
  const [currentVal, setCurrentVal] = useState(0);
  return
   <>
     <Child1 value={currentVal} onChange={setCurrentVal}/>   // you might also pass a function that does some other logic and then calls setCurrentVal
     <Child2 value={currentVal} onChange={setCurrentVal}/>
   </>
}
Reuben S
  • 93
  • 1
  • 10
Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
1

@Jeff Storey The solution seems a bit wrong. The first index is the value and the second index is the function which updates the value.

It should be:

const [currentVal, setCurrentVal] = useState(0);
Yamo93
  • 514
  • 3
  • 12