-1

As the title indicates, i'm looking for a way for the form onChange event to be triggered without user direct interference. This has more to do with Javascript itself but i'm using React to exemplify what i'm looking for:

I have a custom component DropDown:

function DropDown() {
  const [selectedPerson, setSelectedPerson] = useState(people[0])
  const selectRef = useRef()

  useEffect(() => {
    selectRef.current.value = selectedPerson.id
  }, [selectedPerson])

  return (
    <>
      <Listbox value={selectedPerson} onChange={setSelectedPerson}>
        {({ open, disabled, value }) => {
          console.log()
          return (
            <div>
              <Listbox.Button as="div">
                <span>{selectedPerson.name}</span>
              </Listbox.Button>
              <Listbox.Options static style={{ display: open ? 'block' : 'none' }}>
                {people.map(person => (
                  <Listbox.Option key={person.id} value={person} disabled={person.unavailable}>
                    {person.name}
                  </Listbox.Option>
                ))}
              </Listbox.Options>
            </div>
          )
        }}
      </Listbox>
      <div>
        <select ref={selectRef} name="test" id="">
          {people.map(person => (
            <option key={person.id} value={person.id}>
              {person.name}
            </option>
          ))}
        </select>
      </div>
    </>
  )
}

the "pure" is going to be hidden, it's just there so i can try and trigger my onChange event of the form that surrounds the component

import DropDown from './DropDown'
import './App.css'

function App() {
  const onChange = ev => {
    console.log(ev)
  }
  return (
    <div className="App">
      <form onChange={onChange}>
        <DropDown />
      </form>
    </div>
  )
}

export default App

As you can see, in my useEffect, i successfully change the selected value of my component but i want it to trigger the onChange event on the form, same way as it happens when i change the option directly in the Select.

To be clear, I'm trying to avoid prop drilling the onChange function down to the DropDown component.

Is there a way for this to happen?

André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120

1 Answers1

1

This should solve the issue you're having. You can pass the onChange() function to the <Dropdown> component and call the function inside the useEffect:

import DropDown from './DropDown'
import './App.css'

function App() {
  const onChange = ev => {
    console.log(ev)
  }
  return (
    <div className="App">
      <form onChange={onChange}>
        <DropDown onFormChange={onChange}/>
      </form>
    </div>
  )
}

export default App

And then inside the component your useEffect would look something like:

useEffect(() => {
    selectRef.current.value = selectedPerson.id
    props.onFormChange();
  }, [selectedPerson])

Don't forget to add the props argument to the component definition:

function DropDown(props) {
...
}
FSperoni
  • 66
  • 4
  • that's exactly what i'm trying to avoid... but thanks for the answer – André Alçada Padez Mar 19 '23 at 17:56
  • 1
    Oh, I see. Perhaps this might be useful: https://stackoverflow.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually – FSperoni Mar 19 '23 at 18:00
  • yes, it works, with the `document.querySelector('select.freight').dispatchEvent(new Event('change', { 'bubbles': true }))` You can change your answer to include what it says in the other question, i'll accept your answer as correct, even though this is probably going to be closed as duplicate. Thanks anyway – André Alçada Padez Mar 19 '23 at 18:09
  • No worries André, cheers! – FSperoni Mar 19 '23 at 18:55