Gonzalo
Gonzalo

Reputation: 355

Getting Value from a Child Dropdown

I am trying to get the value using the function getValues from react-hook-form from a child component that I have created (bear in mind this is an example and there is some logic of having created the component in this fashion). When I click on "Print Values" it doesn't get the value of authorId. Any ideas?

These are the two components:

const { register, control, getValues } = useForm();

<Button
  onClick={() => {
    console.log(getValues());
  }}
>
  Print Values
</Button>

<FormControl variant="outlined">
  <InputLabel>Author</InputLabel>
  <Controller
    {...register}
    control={control}
    name="authorId"
    render={({ field }) => (
      <CustomDropdown control={control} category="Author" field={field} />
    )}
  />
</FormControl>

CustomDropdown.js

const CustomDropdown = ({ field }) => {
  const [selectedValues, setSelectedValues] = React.useState("");

  <Select
    {...field}
    value={selectedValues || ""}
    onChange={(e) => {
      setSelectedValues(e.target.value);
    }}
  >
    return <MenuItem key="1" value="1">
      Option 1
    </MenuItem>
    <MenuItem key="2" value="2">
      Option 2
    </MenuItem>
  </Select>;
};

Upvotes: 0

Views: 308

Answers (2)

RustyJames
RustyJames

Reputation: 133

If you just need to output the value you should use the current scope

const CustomDropdown = () => {
  const [selectedValues, setSelectedValues] = useState("value 1");
  return (
    <>
    <button onClick={()=>console.log(selectedValues)}> Get value </button>
    <select 
      value={selectedValues}
      onChange={e => setSelectedValues(e.target.value)}>
        <option value="value 1"> Value 1</option>
        <option value="value 2"> Value 2</option>
        <option value="value 3"> Value 3</option>
      </select>
    </>
  )
} 

If you need the value for other purposes use the Context Hook

Edit: Example of passing values from child to parent with the Context Hook. In your case you will need to define the useState in App.js like this:

App.js

import { createContext, useState } from 'react';
import './App.css';
import Child from './Child.js'

export const MyContext = createContext("N0thing")

function App() {
  const [getValue, changeValue] = useState(0)
  return (
    <div className="App">
      <header className="App-header">
      <MyContext.Provider value={{getValue, changeValue}}>
          <Child/>
      </MyContext.Provider>
          Renderd by Parent {getValue}
      </header>
    </div>
  );
}

export default App;

Child.js

import {useContext} from 'react'
import {MyContext} from './App.js'

const Child = () => {
    const myContext = useContext(MyContext)
    return (
        <>
        Renderd by Child {myContext.getValue}
        <button onClick={()=>myContext.changeValue(myContext.getValue + 1)}> Change value from Child Componet </button>    
        </>
    )
}
 export default Child;

I hope I understand you correctly and that this can help.

Upvotes: 0

Abir Taheer
Abir Taheer

Reputation: 2783

There's a couple of things. First, the register method needs to be called with the name of the input. In the controller component you're not calling register

<Controller
  {...register}

Instead change it to:

<Controller
  {...register("authorId")}

Also you're not using the useForm hook to control the value of the CustomDropdown component.

Rather you're controlling the value using its own react state that the useForm hook is unaware of

const [selectedValues, setSelectedValues] = React.useState("");
// ...
onChange={(e) => { setSelectedValues(e.target.value) }}

One solution is to pass the setValue method and value to the CustomDropdown component as properties.

First file

const { register, control, getValues, setValue } = useForm();

const setAuthorIdValue = (value) => setValue("authorId", value);

<Button
  onClick={() => {
    console.log(getValues());
  }}
>
  Print Values
</Button>

<FormControl variant="outlined">
  <InputLabel>Author</InputLabel>
  <Controller
    {...register("authorId")}
    control={control}
    name="authorId"
    render={({ field }) => (
      <CustomDropdown
        control={control}
        category="Author"
        field={field}
        value={getValues("authorId")}
        setValue={setAuthorIdValue}
      />
    )}
  />
</FormControl>

CustomDropdown.js

const CustomDropdown = ({ field, value, setValue }) => {
  return <Select
    {...field}
    value={value || ""}
    onChange={(e) => {
      setValue(e.target.value);
    }}
  >
    return <MenuItem key="1" value="1">
      Option 1
    </MenuItem>
    <MenuItem key="2" value="2">
      Option 2
    </MenuItem>
  </Select>;
};

Upvotes: 1

Related Questions