Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two way data binding in React with Hooks

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;
like image 267
Eric Rovell Avatar asked Sep 02 '25 02:09

Eric Rovell


1 Answers

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}/>
   </>
}
like image 101
Jeff Storey Avatar answered Sep 04 '25 20:09

Jeff Storey