1

I have an object in mydata.js file:

const myData = {
 name: 'John',
 lastname: 'Smith'
}
export default myData

In React component I import that object and pass it in component via props and put in on a page

import myData from './mydata.js'
const ParentComponent = () => {
  return (
   <ChildComponent info={myData} />
  )
}

Then for example in another component, let's named it DataChanger I changed a field in myData object:

 import myData from './mydata.js'     
 const DataChanger = () => {

  const onChangeDataHandler = () => {
    myData.name = 'David'
  }
  return (
    <div>
      <button onClick={() => onChangeDataHandler()}>Data Changer</button>
    </div>
  )
}

In this case, when I click on the button and change a field, I don't have changes in Child Component via props. Is it possible to make myData reactive?

Edit wonderful-allen-v5ddf

keikai
  • 14,085
  • 9
  • 49
  • 68
splincool
  • 141
  • 2
  • 10
  • 2
    Rewrite your app so 1) a common parent imports `myData` and puts it into its `state` 2) `DataChanger` calls a prop function to change the parent's state (this is the default React pattern, and you shouldn't deviate from it needlessly) –  Dec 25 '19 at 14:23
  • I haven't mentioned but in my case, DataChanger is not a child of the Parent component, it is like both (Parent and DataChanger) are in App.js – splincool Dec 25 '19 at 15:02
  • 1
    That's why I spoke of a "common parent", which in your case is `App`. –  Dec 25 '19 at 15:03
  • 1
    You essentially want to implement [this](https://reactjs.org/tutorial/tutorial.html#lifting-state-up), even if that means passing down the state through several layers of components. –  Dec 25 '19 at 15:16

1 Answers1

0

// You need to use state

import initialData from './mydata.js'

const ParentComponent = () => {
    const [myData, setMyData] = useState({ ...initialData });
    const onChangeHandler = (newData) => {
        setMyData({ ...myData, ...newData });
    };
    return (
        <>
            <ChildComponent info={myData} />
            <DataChanger onChangeHandler={onChangeHandler} />
        </>
    );
}

// Then
const DataChanger = (props) => {
    const onButtonClick = (event) => {
        const newData = { name: 'David' };
        props.onChangeHandler(newData);
    };
    return (
        <div>
            <button onClick={onButtonClick}>Data Changer</button>
        </div>
    );
}
Miguel Lattuada
  • 5,327
  • 4
  • 31
  • 44
AlexDevTime
  • 166
  • 4
  • The Component that changes the data isn't the same as the one that displays it. –  Dec 25 '19 at 15:15
  • Your click handler function passes the clickEvent; use `() =>` instead. –  Dec 25 '19 at 15:39
  • I don't understand what you mean. – AlexDevTime Dec 25 '19 at 15:48
  • 1
    When onClick is called, the browser passes the click event as first parameter. So inside your click handler function, `someData` shadows the component's const of the same name and contains the click event instead. Not only do you not need any parameters in your click handler function, using `someData` sabotages it. –  Dec 25 '19 at 16:02