Tanvesh
Tanvesh

Reputation: 125

How to dispatch a change action in input field

I am currently making a small form for an important assignment which demands redux. I want to create a global object which dynamically updates itself after onChange. How do I update the changes in the global object on changing input so I can use it any where ?

here are my files 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))

Upvotes: 2

Views: 1549

Answers (1)

Drew Reese
Drew Reese

Reputation: 203466

It seems like you are asking how to convert from using local component state to redux state.

  1. Move the username, email, phone, and age state into the userReducer function's initialState.

    const initialState = {
      username: "",
      email: "",
      phone: "",
      age: ""
    };
    
  2. Update userReducer to consume an action payload that contains the key and value for the nested state you want to update.

    const userReducer = (state = initialState, action) => {
      switch (action.type) {
        case SET_USER_PROFILE:
          const { key, value } = action.payload;
          return { ...state, [key]: value };
    
        default:
          return state;
      }
    };
    
  3. Update the setUser action creator function to take the key and value you want to update and return the action payload. There's no asynchronous logic here so there's no need to write a Thunk function that is also passed the dispatch function.

    const setUser = (key, value) => ({
      type: SET_USER_PROFILE,
      payload: { key, value }
    });
    
  4. Update the Details component to select the user state from Redux and update the handleChange callback to dispatch the setUser action with the appropriate payload values. Since these are likely supposed to be controlled inputs you'll want/need to specify the value prop on the fields and pass the appropriate state.

    const dispatch = useDispatch();
    const { username, email, phone, age } = useSelector((state) => state.user);
    
    const handleChange = (e) => {
      const { name, value } = e.target;
      dispatch(setUser(name, 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="username"
            value={username}
            className={classes.text}
            onChange={handleChange}
          />
          <TextField
            id="filled-basic"
            label="Phone number"
            variant="filled"
            name="phone"
            value={phone}
            className={classes.text}
            onChange={handleChange}
          />
          <TextField
            id="filled-basic"
            label="Email"
            variant="filled"
            name="email"
            value={email}
            className={classes.text}
            onChange={handleChange}
          />
          <TextField
            id="filled-basic"
            label="Age"
            variant="filled"
            name="age"
            value={age}
            className={classes.text}
            onChange={handleChange}
          />
        </CardContent>
      </Card>
    );
    

Edit how-to-dispatch-a-change-action-in-input-field

enter image description here

Upvotes: 2

Related Questions