1

I have a modal that is triggered on a button click that needs to be populated with an input value that can be edited by the user. When the button is clicked, modal state is updated, but the input either:

a. doesn't reflect the updated state as its value (this happens when I use 'defaultValue' --or--

b. won't let the user edit the value in the input (this happens when I use 'value'.

How can I populate the input with the current state and also be able to edit it? Shouldn't changing the state that the input value is set to trigger a re-render of the modal?

function EditModal(props) {
    const [value, setValue] = useState(props.modalVal);
    const[hidden, setHidden] = useState(true)
    const[initialRender, setInitialRender] = useState(true)
    useEffect(()=>{
        setInitialRender(false)
    },[])
    useEffect(() => {
        setValue(props.modalVal)// <-- why doesn't this update input value?
    }, [props.modalVal]);
    useEffect(()=>{
        if(!initialRender){
            setHidden(false)
        }
    },[value])
    return (
        <Modal hidden={hidden} >
            <Text>Edit Item</Text>
            <form action="submit" onSubmit={props.submit}>
                <Input onChange={props.handleChange} defaultValue={value} />
                <Button>OK</Button>
            </form>
        </Modal>
    )
}
Mark Reed
  • 88
  • 5
  • You most likely should be using `value` instead of `defaultValue` I don't know the implementation of `Input`, but in a normal `input`, `defaultValue` only gets used once, no updates will be reflected. – Brian Thompson Jun 01 '20 at 16:35
  • Are you able to log and see that `props.modalVal` is getting updated correctly? – Brian Thompson Jun 01 '20 at 16:36
  • Really, the simple answer here is don't mirror state from props. Just use `value={props.modalVal}`. – Brian Thompson Jun 01 '20 at 16:39

1 Answers1

2

If you set the value using value then when the user edits it, you need to ensure that the onChange function you specify updates the value so that on the next render, the value is updated.

It looks like you have a value (props.modalVal) that you should use as value (note that you do not need the useEffect or the useState for this, as changing props causes a re-render). What you therefore need to make sure is that props.handleChange changes modalValue

Something like this:

<Input onChange={props.handleChange} value={props.modalValue} />

and in the parent component:

const ParentComponent = ()=> {
  const [modalValue, setModalValue] = useState('initialValue');

  const handleChange = (event) => {
    setModalValue(event.currentTarget.value);
  };

  return (
    <EditModal handleChange={handleChange} modalValue={modalValue} />
  )
}
Ed_
  • 18,798
  • 8
  • 45
  • 71
  • 1
    I could have sworn that I tried this already!! Regardless, it worked. Thanks!! – Mark Reed Jun 01 '20 at 18:16
  • Normally when I'm struggling something new I try the correct way first, don't notice a typo or some minor error, and it therefore doesn't work. I then try other things for 3 hours/days until I realise I was right in the first place..! – Ed_ Jun 01 '20 at 18:19