You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux状态更新缓慢求助:登录需多次点击才返回数据

问题:登录需点击三次才能获取数据,Reducer异步处理错误分析

我在调用API后的Reducer中编写了filter函数,未使用async完成,API调用环节应无问题。已尝试重置并返回状态,但状态无法立即更新为initialState,登录时需点击三次才能拿到返回数据。控制台日志显示问题出在Reducer中,相关代码及日志如下:

Reducer代码

const initialState = {
    users: [],
    newUsers: []
}

export const Users = (state = initialState, action) => {
    let { user, email, password } = action
    switch (action.type) {
        case types.CREATE_USER:
            // call API - POST
            axiosUser.post('users', user)
            return state;

        case types.LOGIN_USER:
            // call api - GET USERS
            const res = axiosUser.get('users')
            res.then((res) => {
                const dataUsers = res.data
                const checkUser = dataUsers.filter(item => item.email === email && item.password === password)
                state.newUsers = checkUser
            })
            console.log(state);
            return state;

        default:
            return state;
    }
}

Login组件代码

const Login = () => {
    const newState = useSelector(state => state.Users.newUsers)
    const dispatch = useDispatch()
    const navigate = useNavigate()
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [submit, setSubmit] = useState(false)

    const handleSignIn = () => {
        if (email !== '' && password !== '') {
            dispatch(act_loginUser(email, password))
            console.log(newState);
            /* newState.find(function (item) {
                if (item.email === email && item.password === password) {
                    navigate('/account')
                }
                return 1
            }) */
        } else {
            setSubmit(true)
        }
    }

控制台日志

UsersReducer.js:25 
{users: Array(0), newUsers: Array(0)}
newUsers: 
Array(1)0: {firstName: 'Phạm', lastName: 'Bình', email: 'phamgiabinh95@gmail.com', password: '98700', id: 1}
length: 1
[[Prototype]]: Array(0)
users: []
[[Prototype]]: Object

Login.js:17 
[]
length: 0
[[Prototype]]: Array(0)

UsersReducer.js:25 {users: Array(0), newUsers: Array(1)}
Login.js:17 []

UsersReducer.js:25 {users: Array(0), newUsers: Array(1)}
Login.js:17 [{…}]
0: {firstName: 'Phạm', lastName: 'Bình', email: 'admin@gmail.com', password: '98700', id: 1}
length: 1
[[Prototype]]: Array(0)

问题根源

  1. Reducer中直接修改原state:Reducer必须是纯函数,不能通过state.newUsers = checkUser直接修改原状态对象,Redux依赖状态的不可变性来检测更新,直接修改会导致状态变化无法被捕获。
  2. Reducer中执行异步操作:Reducer是同步执行的,不能在里面写axios的then回调。异步请求属于副作用操作,必须放到action creator中通过中间件(比如redux-thunk)处理。
  3. dispatch后立即读取旧状态:Redux状态更新是异步的,dispatch调用后组件的useSelector不会立刻拿到新值,此时打印的还是更新前的旧状态。

修复方案

1. 用redux-thunk处理异步Action

把API请求逻辑移到action creator中,拿到数据后再触发同步action更新状态:

// action.js
export const act_loginUser = (email, password) => {
  return async (dispatch) => {
    try {
      const res = await axiosUser.get('users');
      const checkUser = res.data.filter(item => item.email === email && item.password === password);
      dispatch({
        type: types.LOGIN_USER_SUCCESS,
        payload: checkUser
      });
    } catch (err) {
      console.error('登录请求失败:', err);
    }
  };
};

2. 修改Reducer为纯函数

严格返回新的状态对象,不修改原state:

const initialState = {
    users: [],
    newUsers: []
}

export const Users = (state = initialState, action) => {
    switch (action.type) {
        case types.CREATE_USER:
            // 同样需要把POST请求移到action中
            return state;

        case types.LOGIN_USER_SUCCESS:
            // 解构原状态并替换newUsers字段,返回新对象
            return {
                ...state,
                newUsers: action.payload
            };

        default:
            return state;
    }
}

3. 组件中监听状态变化执行跳转

用useEffect监听newState的变化,状态更新后再执行页面跳转:

const Login = () => {
    const newState = useSelector(state => state.Users.newUsers)
    const dispatch = useDispatch()
    const navigate = useNavigate()
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const [submit, setSubmit] = useState(false)

    const handleSignIn = () => {
        if (email !== '' && password !== '') {
            dispatch(act_loginUser(email, password))
            setSubmit(false);
        } else {
            setSubmit(true)
        }
    }

    // 监听newState变化,有匹配用户则跳转
    useEffect(() => {
        if (newState.length > 0) {
            navigate('/account');
        }
    }, [newState, navigate]);

    // ... 组件渲染逻辑
}

内容的提问来源于stack exchange,提问作者Bình Phạm Hữu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:55:45