redux react-bootstrap modal在不将showModal设置为false的情况下消失

8mmmxcuj  于 11个月前  发布在  React
关注(0)|答案(1)|浏览(166)

我有一个登录模式,从react-bootstrap,当我填写用户名和密码,并点击登录,它消失,而无需等待showLoginModal被设置为假.这是组件:

import { Modal } from 'react-bootstrap'
const AccountsMenu: React.FC = () => {
    const dispatch = useDispatch()
    const navigate = useNavigate()
    const accounts = useSelector((state: RootState) => state.accounts)
    const location = useLocation()
    const getCurrentPath = () => location.pathname + encodeURIComponent(location.search)
    useEffect(() => {
        dispatch(getUserInfoAction())
    }, [dispatch])
    
    const registerPage = () => {
        navigate(ROUTES.REGISTER_ROUTE)
    }
    const [showLoginModal, setShowLoginModal] = useState(false)
    const [username, setUsername] = useState<string>('')
    const [password, setPassword] = useState<string>('')
    const [usernameError, setUsernameError] = useState<string>('')
    const [passwordError, setPasswordError] = useState<string>('')
    const login = () => {
        // Check if username and password are not empty
        if (!username.trim()) {
            setUsernameError('Username cannot be empty.')
            return
        } else {
            setUsernameError('')
        }

        if (!password.trim()) {
            setPasswordError('Password cannot be empty.')
            return
        } else {
            setPasswordError('')
        }
        dispatch(actions.loginUser({ username: username, password: password }))
        setUsername('')
        setPassword('')
    }
    useEffect(() => {
        if (accounts.apiSuccess) {
            setShowLoginModal(false)
        }
    }, [accounts.apiSuccess])
    if (accounts.loading) return <li>Loading ...</li>
    return (
        <li className="nav-item dropdown">
            <a className="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                Account
            </a>
            <ul className="dropdown-menu">
                {accounts.userInfo.is_active ? (
                    <li>
                        <a href={'/b/logout?next=' + getCurrentPath()} className="dropdown-item">
                            Logout
                        </a>
                    </li>
                ) : (
                    <>
                        <li>
                            <a href={'/b/login?next=' + getCurrentPath()} className="dropdown-item">
                                Login
                            </a>
                        </li>
                        <li>
                            <button onClick={() => registerPage()} className="dropdown-item">
                                Register
                            </button>
                        </li>
                        <li>
                            <button onClick={() => setShowLoginModal(true)} className="dropdown-item">
                                Login modal
                            </button>
                        </li>
                    </>
                )}
            </ul>
            <Modal show={showLoginModal} onHide={() => setShowLoginModal(false)} centered={true}>
                <div className="d-flex justify-content-center m-3">
                    <ErrorHandling error={accounts.error} loading={accounts.loading} />
                </div>
                <form className="p-4">
                    <div className="form-outline mb-4">
                        <label className="form-label" htmlFor="username">
                            User name:
                        </label>
                        <input
                            type="text"
                            id="username"
                            className={`form-control ${usernameError ? 'is-invalid' : ''}`}
                            value={username}
                            onChange={(e) => {
                                setUsername(e.target.value)
                                setUsernameError('')
                            }}
                        />
                        {usernameError && <div className="invalid-feedback">{usernameError}</div>}
                    </div>
                    <div className="form-outline mb-4">
                        <label className="form-label" htmlFor="password">
                            password:
                        </label>
                        <input
                            type="password"
                            id="password"
                            className={`form-control ${passwordError ? 'is-invalid' : ''}`}
                            value={password}
                            onChange={(e) => {
                                setPassword(e.target.value)
                                setPasswordError('')
                            }}
                        />
                        {passwordError && <div className="invalid-feedback">{passwordError}</div>}
                    </div>
                    <div className="form-outline mt-5 text-center">
                        <button type="button" className="btn btn-primary" onClick={() => login()}>
                            Login
                        </button>
                    </div>
                </form>
            </Modal>
        </li>
    )
}

字符串
到目前为止,我已经尝试了以下方法:
1.我已将登录按钮类型更改为"button"而不是"submit",以防止表单刷新页面。
1.我尝试使用div标签而不是form标签,它仍然表现相同。
1.我尝试将登录名button移出form,但仍然是相同的行为。
我搜索了类似的问题,但没有一个解决这个问题。
问题更新:
我试着注解掉登录的不同部分,导致这一点的部分是dispatch(actions.loginUser({ username: username, password: password }))部分。我不知道我如何才能防止这种情况。或者如果我不能,我怎么能解决这个问题的任何其他方式。

agxfikkp

agxfikkp1#

我找到的解决方案:
所以,正如我之前猜测的那样,问题来自这一部分:dispatch(actions.loginUser({ username: username, password: password }))。换句话说,当Redux商店被更改时,它导致页面重新渲染。但如果我们想更准确地说,这是导致页面重新渲染的部分:

if (accounts.loading) return <li>Loading ...</li>

字符串
所以之前,我们的redux store for account type是这样的:

export interface AccountsStoreType {
    error: string | { [key: string]: string } | null
    loading: boolean
    userInfo: UserInfoType
    registerSuccess: boolean | null
}

export interface UserInfoType {
    username?: string
    first_name?: string
    last_name?: string
    email?: string
    is_active: boolean
    is_staff: boolean | null
}


我们有一个loading和一个error键用于与用户相关的所有内容,例如登录,注销,注册和获取用户信息。
所以,我试着把商店分开:

export interface LoginType {
    loading: boolean
    success: boolean | null
    error: string | { [key: string]: string } | null
}
export interface RegisterType {
    loading: boolean
    success: boolean | null
    error: string | { [key: string]: string } | null
}
export interface LogoutType {
    loading: boolean
    success: boolean | null
    error: string | { [key: string]: string } | null
}
export interface UserInfoType {
    error: string | { [key: string]: string } | null
    loading: boolean
    username?: string
    first_name?: string
    last_name?: string
    email?: string
    is_active: boolean
    is_staff: boolean | null
    about_me?: string
    user_score?: number
    user_contributions?: UserContributionType[]
}
export interface AccountsStoreType {
    login: LoginType
    register: RegisterType
    logout: LogoutType
    userInfo: UserInfoType
}


在分离了类型之后,我在这个答案的开头指出的那一行被转换为:

if (accounts.userInfo.loading) return <li>Loading ...</li>


如您所见,现在它从自己的相关存储中获取loading,注册对渲染此部件没有任何影响。

相关问题