我有一组屏幕(目前为3个),只有当用户在前一个屏幕上执行某些操作时才能访问,如单击一些复选框和几个链接.我正在使用REACTION-CONTEXT将该信息传递给这些屏幕.

代码的精髓如下

Consent.tsx

const onConsentButtonClick = () => {
  setMyContext({userConsent: true});
  navigate("postConsent"); // I am using react-router v6. navigate = useNavigate();
}

PostConsent.tsx

useEffect(() => {
  if(!myContext.userConsent) { // userConsent is always undefined on render
    // show errors and fallback to Consent.tsx
  }
}, []);

这不起作用,因为它看起来像是在上下文更新之前呈现了PostConsend组件.我使用超时验证了这一点.如果我按如下所示更改按钮点击功能,它将正常工作.

const onConsentButtonClick = () => {
  setMyContext({userConsent: true});
  setTimeout(() => {
    navigate("postConsent");
  }, 1000);
}

有没有办法确保在导航到下一个屏幕之前上下文更新已经完成?

我使用的语境是正确的吗?有没有更好的方法来实现这一点?

在我的情况下,props 钻取不是一个选项,也不是通过位置传递状态(因为我不希望浏览器在这些屏幕集上工作).

请务必建议是否有更好的替代方法来实现这一点.

编辑: 以下是我的完整上下文文件

const MyContext = createContext(null);

export function MyProvider({ children }) {
    const [myContext, setMyContext] = useState({});
    return (
   <MyContext.Provider value={{myContext, setMyContext}}>
            {children}
    </MyContext.Provider>
    );
}

export const useMyContext = () => {
    return useContext(MyContext);
}

我在我的组件中使用这个钩子

const {myContext, setMyContext} = useMyContext();

UPDATE:个 基于下面的回答,我编写了一个定制钩子来封装上下文设置部分和实际设置上下文后的导航

type SetContextAndNavigate = {
    context: any,
    navigate: string
}

const defaultHookValues: SetContextAndNavigate = { context: {initialHookValue: "hook"}, navigate: "nowhere" }; 

function useSetContextAndNavigate() {
  const { myContext, setMyContext } = useMyContext();
  const [currentValues, setAndNavigate] = useState(defaultHookValues);
  const navigate = useNavigate();

  const setValuesBeforeNavigation = (args: SetContextAndNavigate) => {
    setAndNavigate(args);
    setMyContext(args.context);
  }

  useEffect(() => {
    if(currentValues.context == myContext) {
        navigate(currentValues.navigate);
    }
  }, [myContext]);

  return setValuesBeforeNavigation;
}

组件中的用法:

const setContextAndNavigate = useSetContextAndNavigate();
setContextAndNavigate({context: {...consents}, navigate: "postConsent"});

推荐答案

您使用上下文的方式基本上是正确的.

问题是,正如您所说,在Reaction中设置状态是异步的,因此它发生在下一个节拍中.

在Vue.js中,有一个nextTick()函数来实现这一点,但在Reaction中,没有这个函数.react 最接近nextTick()的人:

setMyContext(...);
setTimeout(() => {
  navigate(...);
}, 0);

上面的方法很管用,但不是很优雅.处理它的更合适的方法是监听useEffect的状态变化.

在您的例子中,您希望跟踪用户同意的状态,无论它是未完成、同意还是未同意.例如,我们可以使用undefined作为"未完成"状态.

如下所示(在PostConsent内):

useEffect(() => {
  if (typeof myContext.userConsent === 'boolean') {
    // if consented, do something. otherwise, redirect to failure screen
  } else {
    // waiting... show some loading indicator or simply show loading indicator when page mounts and do nothing here, or simply render `null` until `myContext.userConsent` becomes available
  }
}, [myContext]); // This is the important line, to listen for `myContext`

最后,最好的方法是在导航之前判断上下文状态更新:

useEffect(() => {
  if (myContext.userConsent) {
    navigate("postConsent");
  }
}, [myContext]);

...

const onConsentButtonClick = () => {
  setMyContext({userConsent: true});
}

Reactjs相关问答推荐

如何使用React防止并发注册并处理Firestore数据库中的插槽可用性

过滤对象数组并通过迭代对象数组将属性放入新数组

是否将样式应用于父悬停(框架运动)上的子元素?

使用Overpass API Endpoint计算 map 上的面积

TypeError:SearchProduct.get()获得了意外的关键字参数查询'

如何用Reaction做交互式的MathML?

使用筛选器的Primereact DataTable服务器端分页?

在Map()完成React.js中的多个垃圾API请求后执行函数

左边框不在图表中显示

Reaction-路由-DOM v6与v5

useRef()的钩子调用无效

如何解决使用react-hook-form和yup动态创建的输入不集中的问题

在 CrafterCMS Studio 中拖动字段

useEffect 渲染没有依赖数组的组件

为什么 setState 在 React 中不是异步的?

页面加载时不显示数组中的数据

更新 Next.js 路由查询更改的状态会导致无限循环

更新和删除功能不工作 Asp.net MVC React

错误:无效挂钩调用.钩子只能在函数组件的主体内部调用.使用 next/router 时

当页面重新加载react 路由导航到第一页 v6