如何在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
相关产品推荐
相关产品推荐

