我正在实现一个身份验证流,其中我访问导航顶层的AsyncStorage以获取用户。Root
是保存DrawerNavigator
的组件,出于验证逻辑的目的,我想将我的用户参数传递给它。
// app.js
const App: () => Node = () => {
[user, setUser] = useState();
useEffect(() => {
const getUser = async () => {
let u = await storageHelpers.getUser()
if(u !== user) setUser(u);
}
getUser()
}, [user])
console.log('Rendering', user)
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen initialParams={{user: user}} name="Root" component={Root} options={{ headerShown: false }} />
<Stack.Screen name="Product" component={ ProductScreen } options={ defaultOptions } />
</Stack.Navigator>
</NavigationContainer>
);
};
// root.js
const Root = ({route, props, navigation}) => {
const user = route.params ? route.params.user : undefined;
console.log('User?', user, props, route)
return (
<Drawer.Navigator screenOptions={{drawerPosition:"right"}}>
<Drawer.Screen name="Home" component={HomeScreen} options={defaultOptions}
<Drawer.Screen name="Scan History" component={ScanHistoryScreen} options={defaultOptions}/>
<Drawer.Screen name="Languages" component={LanguagesScreen} options={defaultOptions}/>
<Drawer.Screen name="Report a Problem" component={ReportAProblemScreen} options={defaultOptions}/>
{ user
? <Drawer.Screen name="Logout" component={AuthenticationScreen} />
: <Drawer.Screen name="Login" component={AuthenticationScreen} />
}
</Drawer.Navigator>
);
}
日志的结果——
1. app.js renders, user is undefined (expected)
2. root.js renders, user is undefined (expected)
3. useEffect hook finishes it's async operation (expected)
4. app.js renders, user is defined (expected)
5. *No Rerender On Root.js* (unexpected)
我在StackScreen的initialParams中使用用户对象,所以我预计它会导致root
的渲染,但我猜不是。
如何将user对象传递给其余的导航组件?我想让它尽可能简单,我更愿意避免使用减速器(如ReactNavigation示例使用),我希望类似于我的方法将工作。提前感谢!
React导航只在注册和初始化屏幕时分配initialParams
值。在这个阶段,它是undefined
,当App.js
组件获取用户数据并呈现子组件时,包括导航屏幕。initialParams
将不会更新,因为这是下一个渲染而不是屏幕初始化阶段。
因为你不想使用任何全局状态管理,如Redux或React上下文API,你应该将user
道具直接传递给Root
屏幕。
const App: () => Node = () => {
[user, setUser] = useState();
useEffect(() => {
const getUser = async () => {
let u = await storageHelpers.getUser()
if(u !== user) setUser(u);
}
getUser()
}, [user])
console.log('Rendering', user)
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen initialParams={{user: user}} name="Root" component={(props)= <Root user={user} {...props}/>} options={{ headerShown: false }} />
<Stack.Screen name="Product" component={ ProductScreen } options={ defaultOptions } />
</Stack.Navigator>
</NavigationContainer>
);
};
// root.js
const Root = ({route, navigation,user}) => {
console.log('User?', user, route)
return (
<Drawer.Navigator screenOptions={{drawerPosition:"right"}}>
<Drawer.Screen name="Home" component={HomeScreen} options={defaultOptions}
<Drawer.Screen name="Scan History" component={ScanHistoryScreen} options={defaultOptions}/>
<Drawer.Screen name="Languages" component={LanguagesScreen} options={defaultOptions}/>
<Drawer.Screen name="Report a Problem" component={ReportAProblemScreen} options={defaultOptions}/>
{ user
? <Drawer.Screen name="Logout" component={AuthenticationScreen} />
: <Drawer.Screen name="Login" component={AuthenticationScreen} />
}
</Drawer.Navigator>
);
}