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

如何在React+Redux中通过输入框onChange分发action更新全局状态

如何在Redux中实现表单输入动态更新全局对象

我正在做一项要求使用Redux的作业,需要制作一个小型表单,希望创建一个能在onChange事件触发后动态更新的全局对象。请问如何在输入框内容变化时更新该全局对象,以便在应用的任意位置使用?以下是我的相关文件:

Details.js

import React, {useState} from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import TextField from "@material-ui/core/TextField";
import {useSelector , useDispatch} from 'react-redux';
import {setUser} from './Redux/actions';

const useStyles = makeStyles({
  root: {
    minWidth: 400,
    margin: "20px",
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)",
  },
  title: {
    fontSize: 14,
  },
  pos: {
    marginBottom: 12,
  },
  text: {
    width: 300,
    margin: "10px",
  },
});

export default function Details() {
  const classes = useStyles();
  const bull = <span className={classes.bullet}>•</span>;
  const [user , setUsers] = useState({
    username:"",
    email:"",
    phone:0,
    age:0,
    month:"",
    batch:"",
    isPaid:0
  })

  const dispatch = useDispatch();
  const handleChange = (e) => {
    setUsers({ ...user, [e.target.name]: e.target.value });
  }
  
  return (
    <Card className={classes.root}>
      <CardContent>
        <Typography
          className={classes.title}
          color="textSecondary"
          variant="h5"
          gutterBottom
        >
          Enter Your Details
        </Typography>
        <TextField
          id="filled-basic"
          label="Full Name"
          variant="filled"
          name = "name"
          className={classes.text}
          onChange = {handleChange}
        />
        <TextField
          id="filled-basic"
          label="Phone number"
          variant="filled"
          name = "phone"
          className={classes.text}
          onChange = {handleChange}
        />
        <TextField
          id="filled-basic"
          label="Email"
          variant="filled"
          name = "email"
          className={classes.text}
          onChange = {handleChange}
        />
        <TextField
          id="filled-basic"
          label="Age"
          variant="filled"
          name = "age"
          className={classes.text}
          onChange = {handleChange}
        />
      </CardContent>
    </Card>
  );
}

actions.js

export  const SET_USER_PROFILE = 'SET_USER_PROFILE';

export const setUser = name => dispatch => {
    dispatch({
        type:SET_USER_PROFILE,
        payload:name
    })
}

reducers.js

import { SET_USER_PROFILE } from "./actions";

const initialState = {
    
}

function userReducer(state = initialState , action){
    switch(action.type){
        case SET_USER_PROFILE:
            return {...state , name:action.payload};
        
        default:
            return state;
    }

}

export default userReducer;

store.js

import {legacy_createStore as createStore , combineReducers , applyMiddleware} from 'redux'
import thunk from "redux-thunk"

import userReducer from './reducers'

const rootReducer = combineReducers({userReducer});

export const Store = createStore(rootReducer , applyMiddleware(thunk))

解决方案

1. 调整Redux Action,支持全字段更新

当前setUser仅能更新name字段,修改为接收任意用户属性片段,适配所有表单字段的更新需求:

// actions.js
export const SET_USER_PROFILE = 'SET_USER_PROFILE';

export const setUser = (userData) => dispatch => {
    dispatch({
        type: SET_USER_PROFILE,
        payload: userData
    })
}

2. 更新Reducer,合并用户数据

初始化state与表单结构对齐,修改Reducer逻辑以合并传入的所有用户数据:

// reducers.js
import { SET_USER_PROFILE } from "./actions";

const initialState = {
    username: "",
    email: "",
    phone: 0,
    age: 0,
    month: "",
    batch: "",
    isPaid: 0
}

function userReducer(state = initialState , action){
    switch(action.type){
        case SET_USER_PROFILE:
            return {...state, ...action.payload};
        default:
            return state;
    }
}

export default userReducer;

3. 修改Details组件,同步更新Redux Store

移除本地useState,直接从Redux获取数据,输入变化时触发action更新全局状态:

// Details.js
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
import TextField from "@material-ui/core/TextField";
import {useSelector , useDispatch} from 'react-redux';
import {setUser} from './Redux/actions';

const useStyles = makeStyles({
  root: {
    minWidth: 400,
    margin: "20px",
  },
  bullet: {
    display: "inline-block",
    margin: "0 2px",
    transform: "scale(0.8)",
  },
  title: {
    fontSize: 14,
  },
  text: {
    width: 300,
    margin: "10px",
  },
});

export default function Details() {
  const classes = useStyles();
  const bull = <span className={classes.bullet}>•</span>;
  
  // 从Redux Store获取实时用户数据
  const user = useSelector(state => state.userReducer);
  const dispatch = useDispatch();

  const handleChange = (e) => {
    const { name, value } = e.target;
    // 处理数字类型字段的转换
    const updateData = {
      [name]: (name === 'phone' || name === 'age') ? (Number(value) || 0) : value
    };
    // 分发action更新全局状态
    dispatch(setUser(updateData));
  }
  
  return (
    <Card className={classes.root}>
      <CardContent>
        <Typography
          className={classes.title}
          color="textSecondary"
          variant="h5"
          gutterBottom
        >
          Enter Your Details
        </Typography>
        {/* 修正name属性与Redux state键匹配 */}
        <TextField
          id="filled-basic"
          label="Full Name"
          variant="filled"
          name = "username"
          className={classes.text}
          onChange = {handleChange}
          value={user.username}
        />
        <TextField
          id="filled-basic"
          label="Phone number"
          variant="filled"
          name = "phone"
          className={classes.text}
          onChange = {handleChange}
          value={user.phone}
        />
        <TextField
          id="filled-basic"
          label="Email"
          variant="filled"
          name = "email"
          className={classes.text}
          onChange = {handleChange}
          value={user.email}
        />
        <TextField
          id="filled-basic"
          label="Age"
          variant="filled"
          name = "age"
          className={classes.text}
          onChange = {handleChange}
          value={user.age}
        />
      </CardContent>
    </Card>
  );
}

4. 在任意组件获取全局用户对象

通过useSelector即可在应用任意位置获取实时更新的用户数据:

// 示例组件
import { useSelector } from 'react-redux';

function UserProfile() {
  const user = useSelector(state => state.userReducer);
  
  return (
    <div>
      <h3>用户信息</h3>
      <p>姓名:{user.username}</p>
      <p>邮箱:{user.email}</p>
      <p>电话:{user.phone}</p>
    </div>
  );
}

内容的提问来源于stack exchange,提问作者Tanvesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:25:17