Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parent Not Updating on useRecoilState() on undetermined occasions #342

Open
stephanoparaskeva opened this issue Jun 17, 2020 · 0 comments
Open

Comments

@stephanoparaskeva
Copy link

stephanoparaskeva commented Jun 17, 2020

So my Auth flow works just fine, But using recoil, the parent component doesn't rerender on all state updates from children via useSetRecoilState

Atom

export const authFlowAtom = atom<AuthFlowType>({
  key: 'authFlowAtom',
  default: { loading: true, loggedIn: false, pop: true },
});

Parent:

const Navigator = () => {
  const ref = useRef<any>(null);
  const [authFlow, setAuthFlow] = useRecoilState(authFlowAtom);

  const initialCheck = async () => {
    // Here is the Promise that somehow affects rerendering)
    const [val, id] = await Promise.all([st.doesSessionExist(), getUserId()]);
    if (val && id) {
      setAuthFlow({ loading: false, loggedIn: true, pop: true });
    } else {
      setAuthFlow({ loading: false, loggedIn: false, pop: true });
    }
  };

  useEffect(() => {
    initialCheck();
  }, []);


  useEffect(() => {
    console.log(authFlow);
    // sometimes doesnt console log (should always console log when any function uses setAuthFlow)
  });

  const trackLoggedIn = async () => {
    const id = await getUserId();
    const currentRoute = ref.current?.getCurrentRoute?.().name;
    const allowedLocations = ['Login', 'Register'];
    const isCurrentModal = modalNames.includes(currentRoute);

    if (!id && !allowedLocations.includes(currentRoute)) {
      setAuthFlow({ loading: false, loggedIn: false, pop: isCurrentModal });
    }
  };

  return (
    <NavigationContainer
      ref={ref}
      onStateChange={trackLoggedIn}
      theme={navigationTheme}>
      <TopNav authFlow={authFlow} />
    </NavigationContainer>
  );
};

This occurs in a Distant Child;

  const setAuthFlow = useSetRecoilState(authFlowAtom);

  type HandleLogin = ({
    email,
    password,
  }: {
    email: string;
    password: string;
  }) => void;

  const handleLogin: HandleLogin = async payload => {
    const { data } = (await loginReq(payload, setError)) || {};

    if (data) {
      setUserId(data.id).then(() => {
        console.log('called');
        // runs and sets every time
        setAuthFlow({ loading: false, loggedIn: true });
      });
    }
  };

I had to pass authFlow to the child to use, so that the parent subscribes. But the distant child that contains handleLogin gets setAuthFlow from recoilstate.

To fix the issue I've had to use local useState, and just make the Recoil State hold the setState function for the navigator. So really, the children are just calling setState on the parent, remotely.

export type AuthFlowType = {
  loading: boolean;
  loggedIn: boolean;
  pop?: boolean;
};

export type AuthFlowSetType = {
  set: ({ loggedIn, loading, pop }: AuthFlowType) => void;
};

export const authFlowSetAtom = atom<AuthFlowSetType>({
  key: 'authFlowSetAtom',
  default: { set: () => {} },


const Navigator = () => {
  const ref = useRef<any>(null);
  const [authFlow, setAuthFlow] = useState<AuthFlowType>({
    loading: true,
    loggedIn: false,
    pop: true,
  });
  const setAuthFlowSet = useSetRecoilState(authFlowSetAtom);

  const initialCheck = async () => {
    const [val, id] = await Promise.all([st.doesSessionExist(), getUserId()]);
    if (val && id) {
      setAuthFlow({ loading: false, loggedIn: true, pop: true });
    } else {
      setAuthFlow({ loading: false, loggedIn: false, pop: true });
    }
  };

  useEffect(() => {
    setAuthFlowSet({ set: setAuthFlow });
    initialCheck();
  }, []);

  const trackLoggedIn = async () => {
    const id = await getUserId();
    const currentRoute = ref.current?.getCurrentRoute?.().name;
    const allowedLocations = ['Login', 'Register'];

    if (!id && !allowedLocations.includes(currentRoute)) {
      setAuthFlow({ loading: false, loggedIn: false });
    }
  };

  return (
    <NavigationContainer
      ref={ref}
      onStateChange={trackLoggedIn}
      theme={navigationTheme}>
      <TopNav authFlow={authFlow} />
    </NavigationContainer>
  );
};

export default Navigator;
@stephanoparaskeva stephanoparaskeva changed the title Parent Not Updating on useRecoilState() sometimes Parent Not Updating on useRecoilState() when using Promise.all([]) Jun 17, 2020
@stephanoparaskeva stephanoparaskeva changed the title Parent Not Updating on useRecoilState() when using Promise.all([]) Parent Not Updating on useRecoilState() on undetermined occassions Jun 17, 2020
@stephanoparaskeva stephanoparaskeva changed the title Parent Not Updating on useRecoilState() on undetermined occassions Parent Not Updating on useRecoilState() on undetermined occasions Jun 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant