【发布时间】:2021-04-07 11:17:13
【问题描述】:
我有一个简单的 RN 应用程序,到目前为止几乎只有登录。它使用 Apollo GraphQL 调用后端并将用户令牌和名称存储在 React Context 对象中。上下文对象具有用户和 setUser 函数(并在 App.js 中实例化)。登录屏幕在成功登录时从 UserContext 对象调用 setUser。
这一直运行良好,但今天我更新到 React 16.3 并开始收到警告:
无法从不同组件的函数体内更新组件
如果我们收到成功的响应,则列出我调用 setUser 函数的行。
App.js 使用 useState 来跟踪用户和 setUser 函数,并将其放入对象中以传递给 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>
);
}
并且 LoginScreen 从 UserContext 中检索用户和 setUser,当它从 sigin 突变中获取 data 时,尝试将一个简单的用户对象传递给 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>
)
我记得要让这个工作我必须在 useEffect 调用中包装“已经有一个用户”的情况(它调用 props.navigate),我发现其他帖子建议将此代码包装在 useEffect 中将修复警告。但是,如果我将此代码包装在这样的 useEffect 挂钩中:
useEffect(() => {
if (data) {
setUser({
token: data.signin.token,
name: data.signin.user.name,
})
}
})
我收到错误而不是警告:
渲染的钩子比预期的要少。这可能是由于意外的提前退货声明造成的。
任何帮助将不胜感激!
【问题讨论】:
-
数据变量从何而来?
-
这是来自 GraphQL 调用返回的数据。在这种情况下,用户名和令牌。
标签: javascript reactjs react-native apollo