首页 > 解决方案 > Redux - 提交表单时的调度操作

问题描述

在我的反应应用程序中提交登录表单后,我无法为用户设置 redux 状态。

我有一个组件loginScreen,我想onSubmit在函数中定义的登录表单的回调中调度一个动作submitHandler。这个组件很大,所以我把它剪掉了一点,只显示下面导致问题的部分。它是submitHandler提交表单时实际调用的函数,但是没有调度操作。

import React,{useState,useEffect} from 'react'
import {Link} from 'react-router-dom'
import {Form,Button,Row,Col} from 'react-bootstrap'

// Components //
import Message from '../components/Message'
import Loader from '../components/Loader'
import FormContainer from '../components/FormContainer'

// Redux 
import {useDispatch,useSelector} from 'react-redux'
import {login} from '../actions/userActions'

/// LoginScreen ///
// Used for the route /login 
const LoginScreen = ({location,history}) => {
    // state //
    const [email, setEmail] = useState('')
    const [password,setPassword] = useState('')

    // dispatch - Used for calling actions 
    const dispatch = useDispatch()

    // Global State 
    // Gets the global state from redux 
    const userLogin = useSelector(state => state.userLogin)
    const {loading, error, userInfo} = userLogin // Destructure into own vars 

    // submitHandler //
    // This is used when the login button is clicked 
    const submitHandler = (e) => {
        // You prevent defualt as you dont want a page refresh 
        e.preventDefault()
        // Dispatch login action passing email and password 
        dispatch(login(email,password)) // ***This does nothing*** 
        console.log("Pressed") // ***This Executes*** 
    }
return (
        <FormContainer>
            <h1>Sign In</h1>
            <Form onSubmit={submitHandler}>
                <Form.Group controlId='email'>
                    <Form.Label>Email Address</Form.Label>
                    <Form.Control 
                        type='email' 
                        placeholder='Enter email' 
                        value={email}
                        onChange={(e) => setEmail(e.target.value)}>
                    </Form.Control>
                </Form.Group>

                <Form.Group controlId='password'>
                    <Form.Label>Password</Form.Label>
                    <Form.Control 
                        type="password" 
                        placeholder="Enter Password"
                        value={password}
                        onChange={(e) => setPassword(e.target.value)}>
                    </Form.Control>
                </Form.Group>

                <Button type='submit' variant='primary'>
                    Sign In
                </Button>
            </Form>
            <Row className='py-3'>
                <Col>
                    New Customer? 
                    <Link to={redirect ? `/register?redirect=${redirect}` : '/register'}>
                        Register
                    </Link>
                </Col>
            </Row>
        </FormContainer>
        )
}

export default LoginScreen

我的操作login永远不会被调用,它在下面的代码段中定义。

import axios from 'axios'
import {USER_LOGIN_FAIL,USER_LOGIN_SUCCESS,USER_LOGIN_REQUEST} from '../constants/userConstants'
export const login = () => (email,password) => async (dispatch) => {
    try{
        console.log("HERE I AM") //NEVER PRINTED TO CONSOLE
        // Trying to log the user in 
        dispatch({type: USER_LOGIN_REQUEST})
        // Structure the http request firs 
        const config = {
            headers:{
                'Content-Type': 'application/json'
            }
        }
        // Send the http request, the return will be data on the users if succesful
        const {data} = await axios.post('/api/users/login',{email,password,config})
        // Now dispatch user login success 
        dispatch({
            type: USER_LOGIN_SUCCESS,
            payload: data
        })
        // Now set our user to local storage 
        localStorage.setItem('userInfo',JSON.stringify(data))
    }catch(error){
        // Dispatch the error 
        dispatch({
            type: USER_LOGIN_FAIL,
            // See if there is a custom message in error.response.data.message, if so add that too, else add the error.message
            payload: error.response && error.response.data.message ? error.response.data.message : error.message
        })
    }
}

这个动作的reducer在userReducers.js下面显示的文件中定义

export const userLoginReducer = (state={},action) => {
    // What type of action do we have 
    switch (action.type) {
        // This case is for user being logged in  
        case USER_LOGIN_REQUEST:
            return {loading: true}
        // This is on a succesful request, set user object  
        case USER_LOGIN_SUCCESS:
            return {loading: false, userInfo:action.payload}
        // This is on a bad request
        case USER_LOGIN_FAIL:
            return {loading:false, error: action.payload}
        // This is on the user logging out, just return empty object 
        case USER_LOGIN_LOGOUT:
            return {}
        // Default, just return the initial state 
        default:
            return state
    }
}

我还将它添加到store.js文件中的商店,(再次缩短为大文件)。

const reducer = combineReducers({
    productList: productListReducer,
    productDetails: productDetailsReducer,
    cart: cartReducer,
    userLogin: userLoginReducer
})

const store = createStore(
    reducer,
    initialState,
    composeWithDevTools(applyMiddleware(...middleware))
)

我是 redux 的新手,但到目前为止它在管理状态时运行良好,这是我第一次遇到调度操作的问题。这也是我第一次在用户定义的函数中做这件事,而不是像这样的反应钩子useEffect,这有什么限制吗?我正在使用 redux chrome 扩展,看不到任何状态变化。

标签: javascriptreactjsreduxreact-redux

解决方案


推荐阅读