gdubs
gdubs

Reputation: 2754

Reactjs : how to reset the value of a component from parent using hooks

I have a component that uses another component that inputs and spits out values from a textbox. I can get the value that I input from the child component, my issue is resetting the value of the child component. For now, once I do my onadditem function, the autocomplete inputbox would still maintain the value before i clicked the addbutton for the onadditem.

This is the parent component:

const [state, setState] = useState({
  id: props.spendItem.id,
  isNew: (props.spendItem.id == -1), 
  description: '', 
  vendor: ''
});

const onAddItem = (e) => {
  setState({...state, id: -1, description: '', isNew: true, vendor:''});
}

const setAutoCompleteValue = (e) => {
  setState({...state, vendor: e})
}

var newItem = (<div>
  <AutoComplete 
    items={vendors} 
    name='vendor' 
    value={state.vendor} 
    setValue={setAutoCompleteValue}
  />
  <button onClick={onAddItem}>+</button>
</div>);

This is the input component

const AutoComplete = props => {
  const [typedValue, setTypedValue] = useState(props.value.name || '');

  useEffect(() => {
    props.setValue(getValue());
  }, [typedValue]);

  const onChange = (e) => {
  // i process my change for the value here
  }

  const getValue = () => {
    return typedValue;
  }

  return (
    <div>
      <input 
        id='auto_input' 
        name='name' 
        onChange={onChange} 
        value={typedValue}
      />
    </div>
  );
}

export default AutoComplete;

Upvotes: 0

Views: 1355

Answers (1)

Chris B.
Chris B.

Reputation: 5763

This is because you're passing the parent component value to the child, but you're only initializing it in the child state once, and not updating the child the next time the parent changes. As such, setting the value in the parent will not continue to be reflected in the child.

So you need to decide whether you want to store the state in the parent component or inside the Autocomplete itself. I'm not sure exactly what side effects you want to occur when the state changes, but here's a basic example of how you can make the Autocomplete into a dumb component and reset the value from the parent when an item is added. I removed most of the extraneous state from the parent:

const App = () => {
  const [vendor, setVendor] = React.useState("");
  const [items, setItems] = React.useState([]);

  const onAddItem = () => {
    setItems([...items, vendor]);
  }

  React.useEffect(() => {
    setVendor("");
  }, [items])

  return <div>
            <AutoComplete value={vendor} setValue={setVendor}/>
    <button onClick={onAddItem}>+</button>
    <div style={{ padding: 25}}>
      {items.map(item => <div>{item}</div>)}
    </div>
            </div>
}

const AutoComplete = ({ value, setValue}) => {

const onChange = (e) => {
  setValue(e.target.value)
}

const getValue = () => {
  return typedValue;
}
  return (
    <>
        <input id='auto_input' name='name' onChange={onChange} value={value}/>
    </>
)
}

ReactDOM.render(<App/>, document.getElementById("root"))

Codepen here.

Upvotes: 1

Related Questions