简体   繁体   中英

How to pass key:value onChange from select-option in reactjs?

I follow this tutorial and try to modify it a little.

I have this code addRequestForm.js

import { BiPlus } from 'react-icons/bi'
import { useMutation, useQueryClient } from "react-query"
import { addRequest, getRequests } from "../../lib/helper"
import Bug from "./bugRequest"
import Success from "./successRequest"


export default function AddRequestForm({ formData, setFormData }) {

    const queryClient = useQueryClient()
    const addMutation = useMutation(addRequest, {
        onSuccess: () => {
            queryClient.prefetchQuery('requests', getRequests)
        }
    })

    const handleSubmit = (e) => {
        e.preventDefault();
        if (Object.keys(formData).length == 0) return console.log("Don't have Form Data");
        let { sector, contact_name } = formData;

        const model = {
            sector, contact_name
        }

        addMutation.mutate(model)
    }

    if (addMutation.isLoading) return <div>Loading!</div>
    if (addMutation.isError) return <Bug message={addMutation.error.message}></Bug>
    if (addMutation.isSuccess) return <Success message={"Added Successfully"}></Success>


    return (
        <form className="grid lg:grid-cols-2 w-4/6 gap-4 md:px-4 md:mx-auto" onSubmit={handleSubmit}>
            
            <div className="input-type">
                <label htmlFor="sector" className="block text-sm font-medium text-gray-700">
                    Sector
                </label>
                <select
                    id="sector"
                    name="sector"
                    autoComplete="sector-name"
                    className="border w-full px-5 py-3 focus:outline-none rounded-md"
                    
                    onChange={(e) => setFormData({ [e.target.name]: e.target.value })}
               
                >
                    <option value="North">North</option>
                    <option value="South">South</option>
                    <option value="West">West</option>
                    <option value="East">East</option>
                    {/*  */}
                </select>
            </div>


            <div className="form-control input-type">
                <label className="input-group">
                    <span>Contact Name</span>
                    <input type="text" onChange={setFormData} name="contact_name" placeholder="Contact Name Here..“ className="w-full input input-bordered" />
                </label>
            </div>



            <button type="submit" className="flex justify-center text-md w-2/6 bg-green-500 text-white px-4 py-2 border rounded-md hover:bg-gray-50 hover:border-green-500 hover:text-green-500">
                Add <span className="px-1"><BiPlus size={24}></BiPlus></span>
            </button>

        </form >
    )


}

For name=“contact_name” already succeed insert into database (mongodb + mongoose). But, I'm still confuse, how to do the same to select-option?

Already tried these:

onChange={(e) => setFormData({ e.target.name: e.target.value })}
onChange={(e) => setFormData({ sector.name: e.target.value })}
onChange={(e) => setFormData({ [e.target.name][0]: e.target.value })}

Got Syntax error: Unexpected token, expected ",". While I thought this is the right value when I'm consoling these ( result: “sector:myname”).

onChange={(e) => setFormData({ sector: e.target.value })}
onChange={(e) => setFormData({ [e.target.name]: e.target.value })}

No insert into database.

How to write it correctly? I'm using nextjs (i thought the same with reactjs, right?) + @reduxjs/toolkit 1.9.1.

In case needed, here is reducer.js:

import UpdateRequestForm from "./updateRequestForm";
import AddRequestForm from "./addRequestForm";
import { useSelector } from "react-redux";
import { useReducer } from "react";

const formReducer = (state, event) => {
    return {
        ...state,
        [event.target?.name]: event.target?.value
    }
}

export default function FormRequest() {

    const [formData, setFormData] = useReducer(formReducer, {})
    const formId = useSelector((state) => state.app.client.formId)

    return (
        <div className="container mx-auto py-5">
            {formId ? UpdateRequestForm({ formId, formData, setFormData }) : AddRequestForm({ formData, setFormData })}
        </div>
    )
}

try this

        onChange = {(e) => { 
                          let obj = {} ; 
                          obj[e.target.name] = e.target.value;
                          setFormData(obj);
                
                       } 
                    }

I'm not entirely following your use case for the reducer but you could replace it with a simple handleChange function as follows. Just a side note, calling setFormData(//newData) will complete erase what is in there so we first spread the original state and change the value based on the key .

State and handleChange:

  const [formData, setFormData] = React.useState({
    sector: "North",
    contact_name: ""
  });


const handleChange = ({ target }) => {
  // Deconstruct the target
  // Deconstruct the name and value from the target
  const { name, value } = target;
  // Set the state
  setFormData((previousState) => ({
    ...previousState,
    [name]: value,
  }));
};

Usage:

  <select
    placeholder="Select a sector"
    name="sector"
    value={formData.sector}
    onChange={handleChange}
  >
    <option value="North">North</option>
    <option value="South">South</option>
    <option value="West">West</option>
    <option value="East">East</option>
  </select>

  <input
    value={formData.contact_name}
    placeholder="Contact Name"
    name="contact_name"
    onChange={handleChange}
  />

A codesandbox: https://codesandbox.io/s/interesting-kilby-emcyl4?file=/src/App.js:461-615

Also note that you will need to assign a name to the input element. In the example, name is set to sector. As the name value will be used to indicate which key in the state object must be updated.

It's good practice to have controlled input fields. So setting the value of the input to your state will accomplish this. Only thing to remember is you need a default state. I have added it all to the codesandbox if you would like to take a look.

In my case, just use this syntax:

…
 value={formData.sector}
 onChange={setFormData}
…

Case closed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM