简体   繁体   中英

Component not detecting state change using Redux and React without refreshing the component

I am having issues detecting state change from my Redux reducer in a React App. When I change the state within one component, the other component in the app does not receive the update without the component being loaded again or refreshed. Consider the following components:
Component1.js

const Component1 = ({
  getFromDB,
  updateDB,
  db_stuff: { db_stuff }
}) => {
  const id = some-id;

  useEffect(() => {
    getFromDB(id);
    updateDB(id, { data: someUpdate });
  }, [id]);
  
  // this updates the database and dispatches new state change
  const handleUpdateDB = () => {
    updateDB(id, { data: someUpdate });
  };

  return (
    <Fragment>
      <Button
        onClick={handleUpdateDB}
      >
        Update DB
      </Button>
    </Fragment>
  )
};

Component1.propTypes = {
  getFromDB: PropTypes.func.isRequired,
  updateDB: PropTypes.func.isRequired,
  db_stuff: PropTypes.object.isRequired
};

const mapStateToProps = (state) => ({
  db_stuff: state.db_stuff
});

export default connect(mapStateToProps, {
  updateDB,
  getFromDB
})(Component1);

In the above component, when the button is click, the action is called to write to the database and change the app state. Within another component I have the state but it is not detecting the state change. Below is the contents of Component2:
Component2

const Component2 = ({
  getFromDB,
  db_stuff: { db_stuff }
}) => {
  const id = some-id;
  const [openAlert, setOpenAlert] = useState(false);
  const [redirect, setRedirect] = useState(false);

  useEffect(() => {
    getFromDB(id);
  }, [id]);

  const handleNextPageClick = () => {
    // This is were the issue is I believe but I have included the other code in case it is needed  
    // I have tried removing getFromDB(id) but it doesn't help
    // I have tried making the function async and using await getFromDB(id) but this doesn't work either
    getFromDB(id);
    if (db_stuff && db_stuff.data <= someOtherData) {
      setOpenAlert(true);
    } else if (db_stuff && db_stuff.data > someOtherData) {
      setRedirect(true);
    }
  };

  const handleAlertClose = () => {
    setOpenAlert(false);
  };

  return (
    <Fragment>
      //... other components
      <Button
        onClick={handleNextPageClick}
      >
        Next
      </Button>
      <Snackbar
        open={openAlert}
        autoHideDuration={3000}
        onClose={handleAlertClose}
      >
        <Alert onClose={handleAlertClose} severity="info">
          Please wait
        </Alert>
      </Snackbar>
      {redirect ? <Redirect to={`/AnotherComponent`} /> : null}
    </Fragment>
  );
  
};

Component2.propTypes = {
  getFromDB: PropTypes.func.isRequired,
  db_stuff: PropTypes.object.isRequired
};

const mapStateToProps = (state) => ({
  db_stuff: state.db_stuff
});

export default connect(mapStateToProps, {
  getFromDB
})(Component2);

So when the user in Component2 clicks next they will get an alert notifying them to please wait for the user in Component1 to continue. When the user in Component1 clicks next, the database and state is updated. But when the user clicks the button they are notified one more time. If they click the button again, then they are allowed to continue. So the state is only updating after an event occurs in the component (user clicking next page updates the state). I want the state to update in Component2 once there is a state change made from Component1. As of now the button has to be clicked twice. I have seen similar issues but none of the solutions have worked. Any help or guidance is greatly appreciated. Thank you in advance.

So the app runs on two separate machines? Then you expect the update that one user sends to reach the second user. But you use a GET request to get the current state once the component loads. There is no mechanism that subscribes to any state changes from the remote api that happen later. So only a refresh triggers the app to get the updated state.

To get instant updates a Websocket implementation could provide this instant update. But it requires a complete different setup. For now you may reside to polling the remote api periodically. Say every few seconds.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM