【问题标题】: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)

标签: reactjs react-context


【解决方案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
  })

【讨论】:

    猜你喜欢
    • 2018-06-06
    • 2017-10-24
    • 1970-01-01
    • 2022-12-04
    • 2021-09-13
    • 1970-01-01
    • 2021-09-06
    • 2020-05-16
    • 1970-01-01
    相关资源
    最近更新 更多