簡體   English   中英

登錄到其他組件后響應發送狀態以更改 html

[英]React send state after login to other component to change html

我正在做一個項目(symfony API)和 ReactJs 前端,

我有一個登錄頁面,當我收到 201 http 響應時連接到 api 我將用戶重定向到“/”並在 localstorage 中設置令牌但我的導航欄中有問題我有 2 個按鈕 1 個登錄和另一個用於注冊重定向到兩個頁面。

當我登錄時,我想將標題動態更改為包含用戶信息和用戶設置鏈接等的下拉列表......你有什么想法嗎?

這是導航欄組件的代碼:

    import React, {useEffect, useState} from 'react';
import Dropdown from "./Dropdown";
import {Link} from "react-router-dom";


const Navbar = () => {
    const [isloggedin, setIsloggedin] = useState(false);

    useEffect(() => {
        if (!localStorage.getItem('auth')) {
            setIsloggedin(false);
        } else {
            setIsloggedin(true);
        }

    }, [])

    const ToggleMobileMenu = () => {
        const mobile_menu = document.getElementById('mobile-menu')
        if (mobile_menu.classList.contains('mobile-hidden')){
            mobile_menu.classList.remove('mobile-hidden')
        } else {
            mobile_menu.classList.add('mobile-hidden')
        }
    }

    return (
        <nav className="bg-gray-800 w-full p-4">
            <div className="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
                <div className="relative flex items-center justify-between h-16">
                    <div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
                        <button type="button"
                                className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
                                aria-controls="mobile-menu" aria-expanded="false"
                                onClick={ToggleMobileMenu}
                        >
                            <span className="sr-only">Open main menu</span>
                            <svg className="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none"
                                 viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
                                      d="M4 6h16M4 12h16M4 18h16"/>
                            </svg>
                            <svg className="hidden h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none"
                                 viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
                                      d="M6 18L18 6M6 6l12 12"/>
                            </svg>
                        </button>
                    </div>
                    <div className="flex-1 flex items-center justify-center sm:items-stretch sm:justify-start">
                        <div className="flex-shrink-0 flex items-center">
                            <Link to={'/'}><img src={'./assets/logo.png'} width={'150'} alt={''}/></Link>
                        </div>
                        <div className="hidden sm:flex items-center sm:ml-6 flex">
                            <div className="flex space-x-4 items-center">
                                <Link to={'/'}
                                      className="bg-gray-900 text-white px-3 py-2 rounded-md text-sm font-medium"
                                      aria-current="page">Accueil</Link>

                                <Link to={'/products'}
                                      className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Nos
                                    Produits
                                </Link>

                                <Link to={'/delivery'}
                                      className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Livraison</Link>

                                <Link to={'/contact'}
                                      className="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Contact</Link>
                            </div>
                        </div>
                    </div>
                    <div
                        className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
                        <div className={'ml-3 relative'}>
                            {isloggedin ? (
                                <div className={'ml-3 relative'}>
                                    <Dropdown/>
                                </div>
                            ) : (
                                <div className={'ml-3 relative flex'}>
                                    <Link to={'/login'}
                                          className={'hidden md:flex mr-5 text-white bg-red-200 p-3 rounded'}>Se
                                        connecter</Link>
                                    <Link to={'/register'}
                                          className={'hidden md:flex mr-5 text-white bg-red-200 p-3 rounded'}>S'inscrire</Link>
                                </div>

                            )}

                        </div>
                    </div>
                </div>
            </div>
            <div className="sm:hidden mobile-hidden" id="mobile-menu">
                    <div className="px-2 pt-2 pb-3 space-y-1">
                        <Link to={'/'}
                              className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Accueil</Link>
                        <Link to={'/products'}
                              className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Nos Produits</Link>
                        <Link to={'/delivery'}
                              className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Livraison</Link>
                        <Link to={'/contact'}
                              className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Contact</Link>
                        {isloggedin ? (
                            <Link to={'/account'}
                                  className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Mon compte</Link>
                        ) : (
                            <div>
                            <Link to={'/login'}
                                  className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Login</Link>
                                <Link to={'/register'}
                                      className="text-gray-300 hover:bg-gray-700 hover:text-white block px-3 py-2 rounded-md text-base font-medium mobile-link" onClick={ToggleMobileMenu}>Register</Link>
                            </div>

                        )}


                    </div>
            </div>
        </nav>
    )
}
export default Navbar;

這是登錄組件:

import React, {useState} from "react";
import { useHistory } from 'react-router-dom';
import axios from "axios";

const Login = () => {
    let history = useHistory()
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const [success, setSuccess] = useState('');


    const LoginHandler = () => {
        axios.post('http://127.0.0.1:8000/api/login', {
            'username': username,
            'password': password
        })
            .then((r) => {
                console.log(r)
                setError('')
                setSuccess('Vous etes connecté')
                setTimeout(() => {
                    localStorage.setItem('auth', r.data.token)
                    history.push('/', {auth: true})
                }, 3000)
            }).catch((error) => {
                setError("Username ou mot de passe éroné");
        })
    }

    return (
        <div>
            <div className={'text-center font-semibold mt-2'}>
                {error ? (<p className={'text-red-500'}>{error}</p>) : ( '' )}
                {success ? (<p className={'text-green-500'}>{success}</p>) : ( '' )}
            </div>
            <div className="divide-y divide-gray-200">
                <div className="py-8 text-base leading-6 space-y-4 text-gray-700 sm:text-lg sm:leading-7">
                    <div className="relative">
                        <input autoComplete="off" id="username" name="username" type="text"
                               className="peer placeholder-transparent h-10 w-full border-b-2 border-gray-300 text-gray-900 focus:outline-none focus:borer-rose-600"
                               placeholder="Username"
                               onChange={(e) => setUsername(e.target.value)}
                        />
                        <label htmlFor="username"
                               className="absolute left-0 -top-3.5 text-gray-600 text-sm peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-440 peer-placeholder-shown:top-2 transition-all peer-focus:-top-3.5 peer-focus:text-gray-600 peer-focus:text-sm">username</label>
                    </div>
                    <div className="relative">
                        <input autoComplete="off" id="password" name="password" type="password"
                               className="peer placeholder-transparent h-10 w-full border-b-2 border-gray-300 text-gray-900 focus:outline-none focus:borer-rose-600"
                               placeholder="Password"
                               onChange={(e) => setPassword(e.target.value)}
                        />
                        <label htmlFor="password"
                               className="absolute left-0 -top-3.5 text-gray-600 text-sm peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-440 peer-placeholder-shown:top-2 transition-all peer-focus:-top-3.5 peer-focus:text-gray-600 peer-focus:text-sm">Password</label>
                    </div>
                    <div className="flex justify-center pt-6">
                        <button onClick={LoginHandler} className="bg-blue-500 text-white rounded-md px-2 py-1">Se
                            connecter
                        </button>
                    </div>
                </div>
            </div>
        </div>
    )

}

export default Login;

現在你的 useEffect 鈎子:

useEffect(() => {
    if (!localStorage.getItem('auth')) {
        setIsloggedin(false);
    } else {
        setIsloggedin(true);
    }

}, [])

...僅在導航欄的初始渲染時觸發。

您有兩個選擇——我強烈建議使用第二個。


選項 1: useEffect Hook 有一個依賴項列表(傳遞給useEffect的第二個參數。只要該依賴項列表中的任何值發生更改,代碼就會再次運行。因此,為了更新導航欄,您必須添加該 localStorage “狀態”到列表中。但是,我不知道這是否會奏效——這不是做事的“反應方式”。


選項 2:更改您的狀態層次結構。 現在您的層次結構如下所示:

<Navbar>
    <Login>
</Navbar>

在反應中,您應該使用 useState 存儲狀態(除此之外,您還可以向 localStorage 添加auth )。 該狀態應存儲在受該狀態影響的最高階組件中。

解決方案:對導航欄中的用戶對象使用狀態。 將 setUserState 函數傳遞給登錄組件並在成功登錄時觸發 setUserState(在 localStorage.setItem 旁邊)。 將該 userState 添加到上述 useEffect 掛鈎的依賴項列表中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM