在渲染外使用 apollo client mutate 的问题

problem with using apollo client mutate outside render

我想要一个名为 AuthRoute 的自定义组件,不仅可以检查某些数据是否在 redux 中可用,还可以使用 graphql 验证令牌

这是我所做的:

const AuthRoute = ({ component: Component, authUser, ...rest }) => {
  const you_must_go_back_to_login = <Route
    {...rest}
    render={props =>
      (<Redirect to={{
        pathname: '/user/login',
        state: { from: props.location }
      }}
      />)
    }
  />

  const continue_journey = <Route
    {...rest}
    render={props =>
      (<Component {...props} />)
    }
  />

  const [dest, setDest] = useState(you_must_go_back_to_login)
  const [checkThat, setCheckThat] = useState(false)

  useEffect(() => {
    client.mutate({
      mutation: VERIFY_TOKEN_MUTATION,
      variables: { token }
    }).then(result => {
      // setDest(continue_journey)
      setCheckThat(true)
    })
    return () => {
      console.log()
    };
  }, [])

  // if(authUser) {
  if (checkThat) {

    return continue_journey

  } else {
    return you_must_go_back_to_login;
  }
}

这是我需要他们完成的步骤:

  1. 运行 变异

  2. setDest 为 you_must_go_to_login 或 continue_journey

  3. 之一
  4. setCheckThat 或类似的东西根据令牌是否已验证为真或假

  5. return dest 结果

现在我遇到了这个错误:

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.

更新

我将我的代码改成了这个,但我仍然得到同样的错误

const AuthRoute = ({ component: Component, authUser, ...rest }) => {
  const you_must_go_back_to_login = (<Route
    {...rest}
    render={props =>
      (<Redirect to={{
        pathname: '/user/login',
        state: { from: props.location }
      }}
      />)
    }
  />)

  const continue_journey = (<Route
    {...rest}
    render={props =>
      (<Component {...props} />)
    }
  />)

  // const [dest, setDest] = useState(you_must_go_back_to_login)
  const [checkThat, setCheckThat] = useState(false)

  useEffect(() => {
    let isSubscribed = true

    if (isSubscribed) {
      getToken();
    }

    return () => isSubscribed = false
  }, []);

  const getToken = async (sig) => {
    const data = await mutate(VERIFY_TOKEN_MUTATION, { token })
    console.log(data)
    setCheckThat(true);
    console.log(checkThat)
    return;
  };

  return checkThat ? continue_journey : you_must_go_back_to_login;
}

警告不言自明 -

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.

特别是这部分 -

To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

您使用 useEffect 的方式有误。你不应该把你的突变放在 useEffect 里面。您可以做的是 - 在 useEffect.

之外进行突变
const [dest, setDest] = useState(you_must_go_back_to_login)
const [checkThat, setCheckThat] = useState(false)

  client.mutate({
      mutation: VERIFY_TOKEN_MUTATION,
      variables: { token }
    }).then(result => {
      // setDest(continue_journey)
      setCheckThat(true)
    })
    return () => {
      console.log()
    };


  useEffect(() => {
    // if(authUser) {
    if (checkThat) {

      return <continue_journey/>

    } else {
      return <you_must_go_back_to_login/>;
    }
  }, [checkThat])
}

所以现在突变将 运行,然后设置 checkThat 变量。然后 useEffect 将被触发,这将 return 基于 checkThat

的值

错误是在获取数据之前呈现重定向导致的。

Normlly ... 而不是 useEffect 您可以使用简单的 useQuery 并使用条件 loading!data 进行渲染一些 <Loading/> 决定重定向或授予访问权限(呈现重定向或受保护的内容)。

突变通常用于改变远程数据。通过使用查询,您也可以传递变量和 return 答案。

I'm using django graphql jwt and the problem is that verifytoken for that is a mutation

在 general/usually 中,令牌由请求头和 API return 响应或错误(对于 missing/expired 令牌)传递。通常您可以选择查询当前用户是否已登录验证。

... 在这种情况下我们要使用突变

... 相反 client.mutate 我们可以使用钩子 - useMutation or better API example (apollo docs :] ) - 在做出决定之前访问 loading state

const [verifyToken, { data, loading, error }] = useMutation( VERIFY_TOKEN_MUTATION, variables: { token } );

有问题?
- 开始时不调用突变 - loading 不会在开始时为真; - returned 数据。

为了在开始时触发突变我们可以使用 useEffect,对于 returned 数据我们可以使用 onCompleted 处理程序但我们可以简单地使用 data - 应该是 undefined/nulled 开始时,可​​用于条件。

像这样的东西应该可以工作(我们不需要等待等 - dataloadingerror 将自动更新):

useEffect(() => {
  verifyToken(); // ariables passed earlier, can be passed here
}, []);

if( !data ) return <Loading />

return data.someSuccessVerifiedField ? continue_journey : you_must_go_back_to_login;