Search code examples
reactjsreact-hooksmaterial-uireact-functional-component

How to return to old state after searching table React Hooks


here's what I'm trying to do:

  1. Search a table through the search bar and have it return the filtered patients on live changes.
  2. Return all patients as normal before the search happened if there's an empty string in the search bar or if the user clicked cancelSearch button.

Here's the issue:

I cannot get the old state back once the search is over.

Here's my code:

const [patients, setPatients] = useState([

    ])  

 // GET/Fetch all patients, listener for patients

useEffect(() => {
    fetch('api/patients')
    .then(response => response.json())
    .then(json => setPatients(json))

}, [])

const [searched, setSearched] = React.useState("")


  const requestSearch = (searchedVal) => {
    const filteredPatients = patients.filter((patient) => {
      return patient.fullName.toLowerCase().includes(searchedVal.toLowerCase());
    });
    setPatients(filteredPatients);
  };


  const cancelSearch = () => {
    setSearched("");
    requestSearch(searched);
  };

<SearchBar
    value={searched}
    onChange={(searchVal) => requestSearch(searchVal)}
    onCancelSearch={() => cancelSearch()}
  />
      <TableContainer component={Paper} style={{overflow: "hidden"}}>
      <Table className={classes.table} aria-label="simple table">
        <TableHead>
          <TableRow>
            <TableCell><strong>Name</strong></TableCell>
            <TableCell align="right"><strong>Age</strong></TableCell>
            <TableCell align="right"><strong>Condition</strong></TableCell>
            <TableCell align="right"><strong>Diagnosis</strong></TableCell>
            <TableCell align="right"><strong>Supervising Doctor</strong></TableCell>
            <TableCell align="right"><strong>Status</strong></TableCell>
            <TableCell align="center"><strong>Action</strong></TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {patients.map((patient) => (
                        <>
          {patient.status === "Active" &&         
        <Slide direction="up" in={patients} mountOnEnter unmountOnExit>
        <TableRow key={patient._id}>
              <TableCell>{patient.fullName}</TableCell>
              <TableCell align="right">{patient.age}</TableCell>
              <TableCell align="right">{patient.condition}</TableCell>
              <TableCell align="right">{patient.diagnosis}</TableCell>
              <TableCell align="right">{patient.supervisor}</TableCell>
              <TableCell align="right">{patient.status}</TableCell>
              <TableCell align="center">
                  <Tooltip title="Details">
                        <IconButton aria-label="details" component={Link} to={`/patients/${patient._id}`}>
                            <PersonPinIcon />
                         </IconButton>
                        </Tooltip> 
                        <Tooltip title="Delete">
                          <IconButton aria-label="delete" onClick={()=>deletePatient(patient._id)}>
                            <DeleteIcon />
                          </IconButton>
                         </Tooltip> 
              </TableCell>
            </TableRow>
            </Slide>
            }
            </>
          ))}
        </TableBody>
      </Table>
    </TableContainer>

Solution

  • In the set state you can access the previous state, for example, for the typical counter example like this:

    setPatients((prevCounter) => { prevCounter++ });
    

    Actually to call setState with a function is encouraged to maintain the current state value in successive calls and not overwrite the previous. For example if you had set counter twice, only +1 will take place:

    setPatients(prevCounter++);
    setPatients(prevCounter++);
    

    Because you would be doing the ++ both times to the original state value. That said, I would use the set state with a function to keep the previous state, so that it can be used afterwards, like this:

    const previousState;
    setPatients((prevState) => { 
        previousState = prevState;
        return filteredPatients 
    });
    

    (Not debugged code) That way, previous state would be in the const previousState in case you need to set that back.