React Hook 触发器重新渲染,但 React Navigation 不会更新屏幕


我写了一个useAuth钩子。通过这个钩子,我在App.js中使用varpartnerId来构建StackNavigator屏幕。我预计,当我设置/取消设置partnerId时,用户会自动导航到PairingDashboard组件,因为React Navigation会删除其中一个组件

因此,当我运行应用程序时,我会看到仪表板,因为我使用了addPartner('test');。当我单击面板上的按钮时,我看到组件重新渲染,因为<Text>节点从Partner更改为No Partner

但我希望重定向到配对组件

App.js

const AppStack = createStackNavigator();
const App = () => {
const [myId, partnerId, addPartner, removePartner] = useAuth();
addPartner('test'); // for testing right now
return (
<NavigationContainer>
<AppStack.Navigator>
{!partnerId ? (
<AppStack.Screen
name="Pairing"
component={Pairing}
options={{headerShown: false}}
/>
) : (
<AppStack.Screen
name="Dashboard"
component={Dashboard}
options={{title: 'Dashboard'}}
/>
)}
</AppStack.Navigator>
</NavigationContainer>
);
};
export default App;

dashboard.js

const Dashboard = () => {
const [myId, partnerId, addPartner, removePartner] = useAuth();
return (
<SafeAreaView>
<ScrollView>
<Text>Dashboard</Text>
{partnerId ? <Text>Partner</Text> : <Text>No Partner</Text>}
<Button
title="Remove Partner Id"
onPress={() => {
removePartner();
}}
/>
</ScrollView>
</SafeAreaView>
);
};
export default Dashboard;

useAuth.js

const PARTNERID_KEY = 'partnerId';
const MYID_KEY = 'myId';
const useAuth = () => {
const [myId, setMyId] = useState(null);
const [partnerId, setPartnerId] = useState(null);
const removePartner = async () => {
await AsyncStorage.removeItem(PARTNERID_KEY);
setPartnerId(null);
console.log('Removed Partner', partnerId);
};
const addPartner = async (newPartnerId) => {
if (!newPartnerId) {
console.error('newPartnerId is null/undefined');
return false;
}
if (newPartnerId.toUpperCase() === myId.toUpperCase()) {
console.error('newPartnerId and myId are equal');
return false;
}
await AsyncStorage.setItem(PARTNERID_KEY, newPartnerId);
setPartnerId(newPartnerId);
console.log('Added Partner', partnerId);
return true;
};
useEffect(() => {
const init = async () => {
// partner
const storagePartnerId = await AsyncStorage.getItem(PARTNERID_KEY);
if (storagePartnerId) {
setPartnerId(storagePartnerId);
}
// self
let storageMyId = await AsyncStorage.getItem(MYID_KEY);
if (!storageMyId) {
storageMyId = await UUIDGenerator.getRandomUUID();
await AsyncStorage.setItem(MYID_KEY, storageMyId);
}
setMyId(storageMyId);
console.log('Auth init', myId, partnerId);
};
init();
}, [myId, partnerId]);
return [myId, partnerId, addPartner, removePartner];
};
export default useAuth;

我发现不可能像全局单例(例如,像Angular Service(那样使用Hook,因为它不是单例!

答案是在App.js中调用useAuth()一次,并使用React.createContext()将值传递给子组件。

App.js

const AppStack = createStackNavigator();
export const AuthContext = React.createContext();
const App = () => {
const [myId, partnerId, addPartner, removePartner] = useAuth();
const authContext = {myId, partnerId, addPartner, removePartner};
addPartner('test'); // testing
return (
<AuthContext.Provider value={authContext}>
<NavigationContainer>
<AppStack.Navigator>
{!partnerId ? (
<AppStack.Screen
name="Pairing"
component={Pairing}
options={{headerShown: false}}
/>
) : (
<AppStack.Screen
name="Dashboard"
component={Dashboard}
options={{title: 'Dashboard'}}
/>
)}
</AppStack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
};
export default App;

dashboard.js

const Dashboard = () => {
const foo = React.useContext(AuthContext);
return (
<SafeAreaView>
<ScrollView>
<Text>Dashboard</Text>
{foo.partnerId ? <Text>Partner</Text> : <Text>No Partner</Text>}
<Button
title="Remove Partner Id"
onPress={() => {
foo.removePartner();
}}
/>
</ScrollView>
</SafeAreaView>
);
};
export default Dashboard;

最新更新