导航到不使用编程路由的其他屏幕
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>
);
}
您必须在订单上下文中加载才能解决此问题。重新渲染整个导航容器不是一个好主意。
小吃有一个工作示例,它只为订单屏幕加载
我有一个 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>
);
}
您必须在订单上下文中加载才能解决此问题。重新渲染整个导航容器不是一个好主意。
小吃有一个工作示例,它只为订单屏幕加载