1
votes

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.

I have tried everything to fix but nothing works. I didn't even use "useEffect". This happens when I login to account and navigate the user to search page.

loginScreen.js

const validationSchema = Yup.object().shape({
  email: Yup.string()
    .label("Email")
    .email("Enter a valid email")
    .required("Please enter a registered email"),
  password: Yup.string()
    .label("Password")
    .required()
    .min(6, "Password must have at least 6 characters "),
});
const { width, height } = Dimensions.get("window");
class loginScreen extends React.Component {
  state = {
    passwordVisibility: true,
    rightIcon: "ios-eye",
  };

  goToSignup = () => this.props.navigation.navigate("Signup");

  handlePasswordVisibility = () => {
    this.setState((prevState) => ({
      rightIcon: prevState.rightIcon === "ios-eye" ? "ios-eye-off" : "ios-eye",
      passwordVisibility: !prevState.passwordVisibility,
    }));
  };
  handleOnLogin = async (values, actions) => {
    const { email, password } = values;
    try {
      const response = await this.props.firebase.loginWithEmail(
        email,
        password
      );

      if (response.user) {
        this.props.navigation.navigate("App");
      }
    } catch (error) {
      alert("Seems like there is no account like that. Try something else.");
    } finally {
      actions.setSubmitting(false);
    }
  };

searchScreen.js

class searchScreen extends Component {
  apiurl = "";
  _isMounted = false;
  constructor(props) {
    super(props);
    this.state = {
      searchText: "",
      results: [],
      isLoading: true,
    };
  }

  showMovie = async (imdbID) => {
    await axios(this.apiurl + "&i=" + imdbID).then(({ data }) => {
      let result = data;
      this.props.navigation.navigate("Movie", {
        selected: result,
        movieID: imdbID,
      });
    });
  };
  componentDidMount() {
    this._isMounted = true;
    this.initial();
  }
  componentWillUnmount() {
    this._isMounted = false;
  }

  initial = async () => {
    const user = await this.props.firebase.getUser(user);

    try {
      await AsyncStorage.setItem("useruid", user.uid);
    } catch (error) {
      console.log(error);
    }
    const expoToken = await UserPermissions.registerForPushNotificationsAsync();
    if (expoToken) {
      this.props.firebase.setExpoToken(expoToken);
    }
    if (this._isMounted) {
      this.setState({ isLoading: false });
    }
  };
  search = async () => {
    Keyboard.dismiss();
    await axios(this.apiurl + "&s=" + this.state.searchText).then(
      ({ data }) => {
        let results = data.Search;
        if (this._isMounted) {
          this.setState((prevState) => {
            return { ...prevState, results: results };
          });
        }
      }
    );
  };
1

1 Answers

3
votes

After a successful login, you call the navigate function. This navigates to a different component, which means the login component becomes unmounted. The handleLogin function still has more logic to execute though, in your finally statement, you are setting submission to false. When that finally runs there is no mounted component which means there is no state to set.

Moving your submission false state change to before the navigate call and before the alert will solve the problem.

I’d recommend not bothering with it in the case the user actually logs in, because the user is about to visually move to a completely different screen, changing the state doesn’t really help them.