【发布时间】:2021-05-19 04:01:59
【问题描述】:
我正在构建一个带有受保护操作的应用,并希望实现以下流程:
- 匿名用户尝试运行受保护的操作(例如播放视频 - 实质上是修改 React 状态)
- 登录模式弹出,没有任何重定向
- 用户填写凭据并点击登录按钮
- 只要用户登录,任何类型的加载器都会显示(并替换之前的应用树)并停留在屏幕上
- 一旦登录,加载程序就会消失,并且经过身份验证的应用程序会呈现
- 视频开始播放,因为应用知道用户想要执行的操作
我还没有找到一种方法来做到这一点,因为用加载器替换旧的应用程序树,然后将其放回屏幕上会使操作在一个已经取消的组件上运行。
我正在使用一个 <UserProvider> 组件来包装整个树,为它提供authenticated 状态。
Codesandbox 来说明问题:
https://codesandbox.io/s/react-context-callback-l9xe9?file=/src/App.js
const MyContext = React.createContext();
const MyProvider = ({ children }) => {
const [auth, setAuth] = React.useState(false);
const [reset, setReset] = React.useState(false);
const [callback, setCallback] = React.useState(null);
const guard = (cb) => {
auth ? cb() : setCallback(() => cb);
};
React.useEffect(() => {
if (auth) {
setReset(true);
setTimeout(() => {
setReset(false);
}, 1000);
}
}, [auth]);
if (reset) {
return <p style={{ color: "red" }}>I pretend I'm logging you in</p>;
}
return (
<MyContext.Provider
value={{
setAuth,
auth,
callback,
setCallback,
guard
}}
>
{children}
</MyContext.Provider>
);
};
const Child = () => {
const [count, setCount] = React.useState(0);
const mounted = React.useRef(false);
React.useEffect(() => {
mounted.current = true;
return () => {
mounted.current = false;
};
}, []);
const myCallback = () => {
setCount((cnt) => cnt + 1);
};
const { auth, setAuth, guard, callback, setCallback } = React.useContext(
MyContext
);
return (
<div>
logged in: {`${auth}`}
<br />
count: {count}
<br />
{callback && (
<button
onClick={() => {
setAuth(true);
callback();
setCallback(null);
}}
>
pretend login
</button>
)}
<button onClick={() => guard(myCallback)}>
increment (when authenticated)
</button>
</div>
);
};
这可能吗?
【问题讨论】:
-
以目前的逻辑,你不能,你必须提升状态。
标签: reactjs