简体   繁体   English

使用上下文修复 React Native 应用程序中的“无法从不同组件的 function 主体内部更新组件”警告

[英]Fix "Cannot update component from inside function body of different component" warning in React Native app using Context

I have a simple RN app that pretty much only has login so far.我有一个简单的 RN 应用程序,到目前为止几乎只有登录。 It uses Apollo GraphQL to call the backend and stores the user token and name in a React Context object. The context object has the user and a setUser function (and is instantiated in App.js).它使用 Apollo GraphQL 调用后端并将用户令牌和名称存储在 React 上下文 object 中。上下文 object 具有用户和 setUser function(并在 App.js 中实例化)。 The login screen calls setUser from the UserContext object on a successful login.登录屏幕在成功登录时从 UserContext object 调用 setUser。

This has been working fine but today I updated to React 16.3 and started getting the warning:这一直工作正常,但今天我更新到 React 16.3 并开始收到警告:

Cannot update a component from inside the function body of a different component无法从不同组件的 function 主体内部更新组件

And lists the line where I am calling the setUser function if we received a succesful response.并列出我在收到成功响应时调用 setUser function 的行。

The App.js uses useState to track the user and setUser function and puts that in a object to pass into the UserContext.Provider: App.js 使用 useState 来跟踪用户和 setUser function 并将其放入 object 以传递到 UserContext.Provider:

export default function App(props) {
  const [user, setUser] = useState(null)
  const contextVal = { user: user, setUser: setUser }

    return (
      <ApolloProvider client={client}>
        <UserContext.Provider value={contextVal}>
          <View style={styles.container}>
            {Platform.OS === 'ios' && <StatusBar barStyle="default" />}
            <AppNavigator />
          </View>
        </UserContext.Provider>
      </ApolloProvider>
    );
}

And the LoginScreen retrieves user and setUser from the UserContext and when it gets data from the sigin mutation, tries to pass a simple user object to setUser: LoginScreen 从 UserContext 中检索用户和 setUser,当它从 sigin 突变中获取data时,尝试将一个简单的用户 object 传递给 setUser:

  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [signin, { data, error, loading }] = useMutation(SIGNIN_MUTATION)
  const { user, setUser } = useContext(UserContext)

  useEffect(() => {
    if (user) {
      props.navigation.navigate('Main')
    }
  }, [user])

  if (loading) return (
    <View style={styles.main}>
      <Text style={styles.text}>Logging you in!</Text>
      <ActivityIndicator size='large' />
    </View>
  )

  if (data) { // ERROR IS HERE
    setUser({
      token: data.signin.token,
      name: data.signin.user.name,
    })
  }

  return (
    <View style={styles.main}>
      <Text style={styles.welcome}>Welcome to Bravauto!</Text>
      <Text style={styles.error}>{error ? errorMessage(error) : ''}</Text>
      <Text>Please login to continue:</Text>
      <TextInput style={styles.input} onChangeText={(text) => setEmail(text)} placeholder="email" />
      <TextInput style={styles.input} onChangeText={(text) => setPassword(text)} placeholder="password" secureTextEntry={true} />
      <Button title="Login!" onPress={() => signin({ variables: { email: email, password: password } })} />
      <Button title="No Account? Register Here" onPress={() => props.navigation.navigate('Registration')} />
    </View>
  )

I remember that to get this working I had to wrap the "already have a user" case (where it calls props.navigate) in a useEffect call, and I found other posts suggesting that wrapping this code in useEffect will fix the warning.我记得为了让它工作,我必须在 useEffect 调用中包装“已经有一个用户”的情况(它调用 props.navigate),我发现其他帖子建议在 useEffect 中包装此代码将修复警告。 However if I wrap this code in a useEffect hook like this:但是,如果我将此代码包装在这样的 useEffect 挂钩中:

  useEffect(() => {
    if (data) {
      setUser({
        token: data.signin.token,
        name: data.signin.user.name,
      })
    }
  })

I get an error instead of a warning:我收到错误而不是警告:

Rendered fewer hooks than expected.渲染的钩子比预期的少。 This may be caused by an accidental early return statement.这可能是由于意外的提前退货声明造成的。

Any help would be much appreciated!任何帮助将非常感激!

You will want to include the data field in the list of ones the useEffect is using:您需要将数据字段包含在 useEffect 使用的列表中:

useEffect(() => {
    if (data) {
      setUser({
        token: data.signin.token,
        name: data.signin.user.name,
      })
    }
  }, [data])

Oops, forgot to post that I eventually found the answer to this.哎呀,忘了发帖说我最终找到了这个问题的答案。 The solution was to use the callbacks provided by Apollo:解决方案是使用 Apollo 提供的回调:

  const [signin, { loading }] = useMutation(SIGNIN_MUTATION, {
    onCompleted: (data) => {
      setAuth(data.signin.token);
    },
    onError: (errorMsg) => {
      setError(errorMessage(errorMsg));
    }, 
    errorPolicy: "none"
  });

After changing to this approach everything works fine.更改为这种方法后,一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 警告:无法从不同组件的函数体内部更新组件。 (反应原生) - Warning: Cannot update a component from inside the function body of a different component. (React Native) 无法从不同组件警告的 function 主体内部更新组件 - Cannot update a component from inside the function body of a different component warning 反应警告:无法从不同组件的函数体内部更新组件 - React Warning: Cannot update a component from inside the function body of a different component React 无法从不同组件的 function 主体内部更新组件 - React Cannot update a component from inside the function body of a different component 无法从不同组件的 function 主体内部更新组件 - React Native? - cannot update a component from inside the function body of a different component - React Native? React Native,无法从不同组件的 function 主体内部更新组件 - React Native, Cannot update a component from inside the function body of a different component 警告:无法从不同组件的 function 主体内部更新组件。 在 TouchableOpacity - Warning: Cannot update a component from inside the function body of a different component. in TouchableOpacity 警告:在渲染不同的组件(`History`)时无法更新组件(`App`) - Warning: Cannot update a component (`App`) while rendering a different component (`History`) React-Native:无法在呈现不同组件时更新组件 - React-Native: cannot update a component while rendering a different component 从 React-Native 中的不同屏幕组件在 App 中调用 function - Calling a function in App from a different Screen component in React-Native
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM