用户授权后如何在所有子组件之间传递状态?

Posted

技术标签:

【中文标题】用户授权后如何在所有子组件之间传递状态?【英文标题】:How to pass state between all child components after user authorization? 【发布时间】:2021-02-07 04:23:28 【问题描述】:

服务器正在返回用户数据。特别是,我对他的权利感兴趣。有了这些权限,我将渲染组件。我正在考虑将这些数据传递给组件并进行一些检查。所有路由都在 index.js 中

import Notfound404 from './components/404/404NotFound'
import UserContext from './UserContext'

const Router = () => 

    const [user, setUser] = useState(null)

    return (
        <React.StrictMode>
            <UserContext.Provider value=user, setUser>
                <CookiesProvider>
                    <BrowserRouter>
                        <Switch>
                            <Route exact path='/' component=Auth/>
                            <Route exact path='/settings' component=Settings/>
                            <Route exact path='/event-logs' component=EventLog/>
                            <Route component=Notfound404 status=404/>
                        </Switch>
                    </BrowserRouter>
                </CookiesProvider>
            </UserContext.Provider>
        </React.StrictMode>
    )

在 Auth.js 中设置用户数据

import UserContext from '../../UserContext'

export const Auth = () => 

    const user, setUser = useContext(UserContext)

    const [username, setUsername] = useState('')
    const [password, setPassword] = useState('')
    const [token, setToken] = useCookies(['qr-token'])

    useEffect(() => 
        if (token['qr-token']) window.location.href = '/settings'
    , [token])

    const credentials = 
        username: username,
        password: password
    

    const sendCredentials = () => 
        axios.post(`http://127.0.0.1:8000/api/v1/auth/`, credentials, 
            headers: 
                'Content-type': 'application/json',
            
        )
            .then(resp => 
                setToken('qr-token', resp.data.token);
                setUser(resp.data)
            )
            .catch(error => console.log(error.response))
    

    return !token['qr-token'] &&
        <div className=styles.authContainer>
            <label htmlFor='username'>Username</label>
            <input id='username' type='text' placeholder='username'
                   onChange=evt => setUsername(evt.target.value)
            />
            <label htmlFor='password'>Password</label>
            <input id='password' type='password' onChange=evt => 
                setPassword(evt.target.value)/>
            <button onClick=sendCredentials>Sign In</button>
        </div>
    )

在 index.js 中,我在授权后获取用户数据。但在 settings.js 中使用数据为空

export const Settings = () => 

    const user, setUser = useContext(UserContext)
    console.log(user) # null
....

可能我做错了什么,我正在寻求您的帮助。谢谢。

【问题讨论】:

能否提供UserContext文件的内容? 没什么特别的) import createContext from 'react' export const UserContext = createContext(null) 【参考方案1】:

正如 Saba 所指出的,问题在于刷新页面以清除上下文。这是通过以下几行完成的:

useEffect(() => 
    if (token['qr-token']) window.location.href = '/settings'
, [token])

不要在单页应用程序中使用常用的重定向方法。相反,使用

const history = useHistory();
useEffect(() => 
    if (token['qr-token'])
        history.push('/settings');
, [token])

这不会导致页面重新加载,从而使您的上下文保持活跃。

【讨论】:

完美运行!太感谢了。但是如果页面被刷新,数据就会丢失。也许正如 Saba 建议的那样将它们存储在本地存储中? @ВалерийСиволапенко 是的,您需要某种方式来保存登录令牌。 localStorage 是您当前设置的最佳选择。只需保存 qr-token 并在您的网站加载时读取它。 好的!谢谢!【参考方案2】:

我认为在重定向到设置页面时正在发生刷新。重新加载会导致上下文值被清除(简单地说,因为上下文的值来自一个状态,并且该状态由于刷新而丢失)。要解决此问题,您可以将身份验证数据数据存储在 localStorage 中,并在它为 null 时为其分配上下文值。

【讨论】:

我还以为是window.location的原因 如果用户以某种方式从本地存储中删除了数据,只是注销它?我只是不知道什么是最好的选择。我已经做了一周的前端) 如果 localStorage 被清除并且页面刷新发生,上下文将再次为空。正如西蒙所说,另一种方法是使用不会导致任何刷新的 history.push() 。但是,如果发生任何刷新,如果它没有存储在 localStorage 中,上下文将再次变为 null。【参考方案3】:

useContext() 提供了一个已经传下来的 dispatch 函数 来自 Store 组件。 dispatch 函数接受两个参数, 一种动作,以及用于更新全局状态的有效负载。这 然后 useContext() 函数将返回一个更新的全局状态。

const  state, dispatch  = useContext(MyContext);

在您的代码中setUser 必须使用包含操作类型和有效负载的参数触发。

例如。

setUser(
    type: "SET_USER",
    payload: resp.data
  )

【讨论】:

以上是关于用户授权后如何在所有子组件之间传递状态?的主要内容,如果未能解决你的问题,请参考以下文章

this.props.match.params 授权后传入子组件

React router onEnter 选项 vs 组件生命周期检查授权用户的方法

2012远程授权数量破解

如何监听通知授权状态的变化

如何在所有请求标头中传递授权令牌 - Spring Boot java

微服务的用户认证与授权杂谈(下)