【问题标题】:React Hook triggers re-render but React Navigation doesn't update screensReact Hook 触发重新渲染,但 React Navigation 不更新屏幕
【发布时间】:2020-07-29 19:02:03
【问题描述】:

我写了一个useAuth 钩子。从这个钩子中,我使用 App.js 中的 var partnerId 来构建 StackNavigator 屏幕。我希望,当我设置/取消设置 partnerId 时,用户会自动导航到 PairingDashboard 组件,因为 React Navigation 会删除其中一个。 (如here在第一个代码sn-p之后描述的)

所以当我运行应用程序时,我会看到仪表板,因为我使用了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;

【问题讨论】:

    标签: reactjs react-native react-hooks react-navigation


    【解决方案1】:

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

    答案是在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;
    

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 2020-06-12
      • 2018-01-17
      • 1970-01-01
      • 2022-06-22
      相关资源
      最近更新 更多