2

In my ReactHooks/Typescript app, I have a Navigation component, that renders a PatientInfo component. The PatientInfo child is rendered conditionally based on what props it is passed, as decided by a searchbox in another child component - MyPatients.

In this structure, I am getting the following error:

et

Navigation.tsx:

// code....
<Route exact path="/" component={MyPatients} />
<Route
    exact
    path="/Pasient"
    render={() => (
         <PatientInfo
              setName={setName}
              setSchema={setSchema}
              patientID={patientID}
          />
    )}
/>
// code....

MyPatients:

const MyPatients = (props: { history: History }) => {
    localStorage.clear();
    const [patientID, setPatientID] = useState(
        localStorage.getItem('myData') || '',
    );

    useEffect(() => {
        localStorage.setItem('myData', patientID);
    }, [patientID]);
    return (
        <>
            <div className="search-container"></div>
            <Row gutter={[60, 40]} justify={'center'}>
                <Col span={1000}>
                    <p>Søk med personnummer for å finne en pasient</p>
                    <Search
                        style={{ width: 400 }}
                        className="search-bar"
                        placeholder="Søk etter en pasient!"
                        onSearch={(value: string) => setPatientID(value)}
                    />
                </Col>
            </Row>
            {patientID &&
                props.history.push({ pathname: 'Pasient', state: patientID })}
        </>
    );
};
export default MyPatients;

I am not familliar with this issue, and don't understand what's happening. My educated guess is that React doesn't like the fact that the state of the parent component is being updated by functions passed to the children, which again are dependant on the props passed along with it. Am I on to something? Any ideas as to what is causing this if not?

Any help is appreciated.

Rostyslav
  • 2,606
  • 9
  • 17
Turtleneck
  • 105
  • 1
  • 9

1 Answers1

2

You are navigating with history.push on each render.

As @HMR mentioned in the comment, you have to remove navigation from JSX template and add it into a separate effect.

const MyPatients = (props: { history: History }) => {
  localStorage.clear();
  const [patientID, setPatientID] = useState(
    localStorage.getItem("myData") || ""
  );

  useEffect(() => {
    localStorage.setItem("myData", patientID);
  }, [patientID]);

  // separate effect here
  useEffect(() => {
    if (patientID) {
      props.history.push({ pathname: "Pasient", state: patientID });
    }
  }, [props, patientID]);

  return (
    <>
      <div className="search-container"></div>
      <Row gutter={[60, 40]} justify={"center"}>
        <Col span={1000}>
          <p>Søk med personnummer for å finne en pasient</p>
          <Search
            style={{ width: 400 }}
            className="search-bar"
            placeholder="Søk etter en pasient!"
            onSearch={(value: string) => setPatientID(value)}
          />
        </Col>
      </Row>
    </>
  );
};
export default MyPatients;

EDIT

This might cause your error:

<PatientInfo
  setName={setName}
  setSchema={setSchema}
  patientID={patientID}
/>

If you call setName or setSchema on render of PatientInfo then Navigation state gets updated before PatientInfo render is finished.

Rostyslav
  • 2,606
  • 9
  • 17
  • Ok, I understand. However, when making this change, it seems to load something incorrectly immediately, not letting me fill the searchfield. Im also getting an instant 500 error from the server I am getting data from. – Turtleneck Jul 02 '20 at 11:18
  • I figured it out. Adding the short-circuit to the new useeffect lets the app behave as it should (`useEffect(() => { patientID && props.history.push({ pathname: 'Pasient', state: patientID }); }, [props, patientID]); `) – Turtleneck Jul 02 '20 at 11:20
  • ... but this is still giving me the error. any ideas? – Turtleneck Jul 02 '20 at 11:22
  • I spoke too soon. The error is indeed there still. However, i dont really understand why. When writing the above comment, I was not getting the error - then suddenly now I am. – Turtleneck Jul 02 '20 at 11:32
  • any ideas, @Rostyslav? I cant seem to get it to work. – Turtleneck Jul 02 '20 at 11:53
  • That makes sense. The thing is, their respective statefields are used by other childre of Navigation, so state has to reside in Navigation. Do you have a suggestion for how I can circumvent the update-issue? – Turtleneck Jul 02 '20 at 12:12
  • @MariusZ put your "statefields" in context [React Context API](https://en.reactjs.org/docs/context.html). Checkout my answer on [this question](https://stackoverflow.com/questions/61984106/how-to-use-react-hooks-on-react-native-with-react-navigation/61984321#61984321) It is for React-Native but context API is platform-agnostic. – Rostyslav Jul 02 '20 at 12:18