导航到不使用编程路由的其他屏幕

Navigating to other screens not working with programmatic routes

我有一个 Routes 组件,returns Stack.Screen 路由基于 user 状态,或者加载屏幕取决于来自的 loading 状态上下文。

出于某种原因,当调用 navigation.nagivate 更改屏幕时,它只是重定向回 initialRouteName 所在的位置。

我怀疑这是因为加载程序没有返回任何路由,并且 navigation.navigate 调用在某处丢失了,但我不确定。

MVCE https://codesandbox.io/s/morning-glitter-b8w5j?file=/src/App.js

Routes.js

function Routes() {
  const { loading } = useContext(AppContext);
  const { user } = useContext(AuthContext);

  if (loading) {
    return <Text>Loading</Text>;
  }

  return (
    <NavigationContainer>
      {user ? (
        <Stack.Navigator initialRouteName="Home">
          <Stack.Screen name="Home" component={HomeScreen} />
          <Stack.Screen name="Order" component={OrderScreen} />
        </Stack.Navigator>
      ) : (
        <Stack.Navigator initialRouteName="Login">
          <Stack.Screen name="Login" component={LoginScreen} />
        </Stack.Navigator>
      )}
    </NavigationContainer>
  );
}

OrderScreen.js(有问题的路线行不通)

function OrderScreen({ order_id }) {
  const { order, getOrder } = useContext(OrderContext);
  useEffect(() => {
    getOrder(order_id);
  });
  return (
    <View>
      <Text>Order</Text>
      <Text>{order}</Text>
    </View>
  );
}

OrderProvider.js(调用 getOrder 的地方)

const OrderContext = createContext({});
function OrderProvider({ children }) {
  const [order, setOrder] = useState(null);
  const { setLoading } = useContext(AppContext);
  return (
    <OrderContext.Provider
      value={{
        order,
        setOrder,
        getOrder: (orderId) => {
          setLoading(true);
          setTimeout(() => {
            setOrder(orderId);
            setLoading(false);
          }, 1000);
        }
      }}
    >
      {children}
    </OrderContext.Provider>
  );
}

问题不在于导航,而在于您在上下文中的 'loading' 状态。

因此,当您打开订单屏幕时,您在 AppContext 中将加载设置为 true,这会导致路由中的 NavigationContainer 重新呈现,从而重置导航状态。

const OrderContext = createContext({});
function OrderProvider({ children }) {
  const [order, setOrder] = useState(null);
  const [orderLoading, setOrderLoading] = useState(false);
  const { setLoading } = useContext(AppContext);
  return (
    <OrderContext.Provider
      value={{
        order,
        setOrder,
        orderLoading,
        getOrder: (orderId) => {
          setOrderLoading(true);
          setTimeout(() => {
            setOrder(orderId);
            setOrderLoading(false);
          }, 1000);
        }
      }}
    >
      {children}
    </OrderContext.Provider>
  );
}

您必须在订单上下文中加载才能解决此问题。重新渲染整个导航容器不是一个好主意。

小吃有一个工作示例,它只为订单屏幕加载

https://snack.expo.io/@guruparan/9be728