'Getting prop from child everytime the prop changes

So in this case `

getDataFromChild(val) {
   this.setState({currentCurrency: val})
}
render() {
   return (
   <div className="App">
      <Navbar sendData = {this.getDataFromChild} />
   </div>`

I am getting data from Navbar child and setting a new state, but when this data changes, it doesn't change parent's state. What should I do?



Solution 1:[1]

I think what you want to do has to be managed a different way in React.

In react, all data flows Down (from Parent to child) not the other way around. If the child has certain data that the parent needs it really should be data that the Parent has which is passed to the child as a prop. (If the child needs to be the place where that data is updated then the parent should pass to the child a function which will set that state).

Even if you are using Redux (in redux there is just one parent Provider of all data) and each child mutates the state of that one Parent (Singleton). One source of data for all children. When using React-Redux your App looks like:

return (
<ReduxProvider>
  <App />
</ReduxProvider>
)

Similar to Redux is the concept of Providers where there is a parent component where you can useState() or (useReducer()) and pass the dispatch/stateUpdater to all the children of that Provider. Typically, you place that Provider close to the top level (it wraps <App/>).

With the use of Providers your App looks:

return (
<UserProvider> {/* contains user.id needed to get notifications */}
  <NotificationsProvider> {/* makes a request like /api/{user.id}/notifications */}
    <App /> {/* contains a navbar which displays all notifications */}
   </NotificationsProvider>
</UserProvider>
)

Even if you don't want to use Providers at all (the advantage of providers is you don't have to pass props to each Child component directly) the structure must remain the same the Parent must provide props to the child (to do the opposite might be possible but is considered an anti-pattern).

const App = () => {
  const [notifications, setNotifications] = useState([]);
  useEffect(() => {
    // where we make an API req to get Notifications
    getNotifications(setNotifications)
    // then run setNotifications to what is returned from the API
  }, []);
  return (<div className="App">
      <Navbar
        notifications={notifications}
        setNotifications={setNotifications}
      />
   </div>);
}

const Navbar = ({ notifications, setNotifications }) => {
return (
  <nav>
    <div>{renderNotifications(notifications)}</div>
      <button
        onClick={
    () => setNotifications([...notifications, newNotification])}
       > Add Notification
    </button>
  </nav>
);

If you are using Providers you don't have to directly pass the props from the Parent to the child: your child can just do:

import { useNotifications, dispatch } from 'providers/notifications';

const Navbar = () => {

const notifications = useNotifications();

const [newNotification, setNewNotification] = useState();
const addNotifications = () => {
  dispatch({type: 'ADD', payload: newNotification })
};
return (
<nav>
  {renderExistingNotifications(notifications)}
  <div>
    <input
      type='text'
      value={newNotification}
      onChange={e => setNewNotification(e.target.value)}
    />
    <button onClick={() => addNotification()}>
      Submit Notification
    </button>
  </div>
</nav>
);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1