简体   繁体   中英

Can't perform a React state update on an unmounted component warning in Parent functional component when Child functional component redirects

I have a parent component UserLogInPage and a child component SignIn (both are functional components).

In SignIn child component, I redirect if authResult is true

{authResult ? <Redirect to="/"></Redirect> : null}

and I trigger the loginUser action like so to check if the credentials a user enters is correct (this dispatch is in my handleSubmitSignInValues handler inside the SignIn child component):

dispatch(loginUser(signInValues)).then((response) => {
      console.log(response);
      setAuthResult(response.payload.auth);
      setMessage(response.payload.message);
      setUserData(response.payload.userData);
    });

My problem is that I keep getting the warning

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
    in SignIn (at UserLogInPage.component.jsx:59)
    ...

May I ask why this is happening and how I can fix this? This warning only started appearing after I tried redirecting. I've tried doing the redirect in a useEffect instead but that didn't help too.

SignIn component

const SignIn = () => {
  const classes = useStyles();
  const dispatch = useDispatch();
  const [signInValues, setSignInValues] = useState({
    email: "",
    password: "",
    showPassword: false,
  });
 
  const [authResult, setAuthResult] = useState("");
  const [message, setMessage] = useState("");
  const [userData, setUserData] = useState({});
 
  const handleChange = (prop) => (event) => {
    setSignInValues({ ...signInValues, [prop]: event.target.value });
  };
 
  const handleClickShowPassword = () => {
    setSignInValues({
      ...signInValues,
      showPassword: !signInValues.showPassword,
    });
  };
 
  const handleMouseDownPassword = (event) => {
    event.preventDefault();
  };
 
  const handleSubmitSignInValues = (event) => {
    if (signInValues.email === "" || signInValues.password === "") {
      alert("Please enter all required fields");
      return event.preventDefault();
    } else if (signInValues.password.length < 8) {
      alert("Your password is too short :( Make it longer than 8 maybe?");
      return event.preventDefault();
    }
    console.log(signInValues);
 
    dispatch(loginUser(signInValues)).then((response) => {
      console.log(response);
      setAuthResult(response.payload.auth);
      setMessage(response.payload.message);
      setUserData(response.payload.userData);
    });
  };
 
  return (
    <Container maxWidth={"sm"}>
      <Typography component={"span"} className={classes.insideContainerStyle}>
        <TextField
          className={classes.textfieldStyle}
          required
          id="email"
          label="Email"
          onChange={handleChange("email")}
          fullWidth
          helperText="Enter your email here"
        />
        <FormControl className={classes.textfieldStyle}>
          <InputLabel htmlFor="standard-adornment-password">
            Password * (min 8 characters)
          </InputLabel>
          <Input
            required
            id="standard-adornment-password"
            type={signInValues.showPassword ? "text" : "password"}
            value={signInValues.password}
            onChange={handleChange("password")}
            endAdornment={
              <InputAdornment position="end">
                <IconButton
                  aria-label="toggle password visibility"
                  onClick={handleClickShowPassword}
                  onMouseDown={handleMouseDownPassword}
                >
                  {signInValues.showPassword ? (
                    <Visibility />
                  ) : (
                    <VisibilityOff />
                  )}
                </IconButton>
              </InputAdornment>
            }
          />
        </FormControl>
        <div></div>
        <br></br>
        <br></br>
        <br></br>
        <br></br>
 
        <Button
          onClick={(e) => handleSubmitSignInValues(e)}
          variant="contained"
          color="secondary"
        >
          Log Me In!
        </Button>
        <div></div>
        ...
        {authResult ? <Redirect to="/"></Redirect> : null}
      </Typography>
    </Container>
  );
};
 
export default SignIn;

Edit: Can I just ignore this?

The response handler in the dispatch's then block is called asynchronously and when it's executing the component is no longer in the DOM (the redirect happened). You're trying to update the state ( setAuthResult , setMessage etc) and React is warning you it can't perform a state update on an unmounted component.

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