Hey Sam,
I’ve dealt with similar issues before but my previous way was really in the early days of React where features were a bit limited. I basically set the value in the parent’s state and pass it to the dumb component(s). This does require you to manually control when the component should re-render in `shouldComponentUpdate`. It’s messy and gets quite convoluted.
Another method is is to do a callback function which would change the input function to:
inputKeyDown = (e, callback) => {
const val = e.target.value;
this.setState({ value: val });
if (e.key === 'Enter' && val) {
if (this.state.tags.find(tag => tag.toLowerCase() === val.toLowerCase())) {
return;
}
this.setState({ tags: [...this.state.tags, val]});
callback();
} else if (e.key === 'Backspace' && !val) {
this.removeTag(this.state.tags.length - 1);
}
}
and the dumb component:
const Search = (props) => {
clearInput = () => {
this.tagInput.value = null;
}
handleKeyDown = (e) => {
props.onKeyDown(e, this.clearInput);
}
return (
<div className="searchContainer">
<input type="text" onKeyDown={this.handleKeyDown} ref={c => { this.tagInput = c; }} />
<button onClick={props.submit} type="submit" value="Submit" className="primaryButton">Search</button>
</div>
)
}
Now the last option and probably the most appropriate one is to use React’s Hook API. I actually haven’t done a lot of work with it so I left this to last, but I found this article, and by using the, and using it I did get it working:
const Search = React.forwardRef((props, ref) => {
const innerRef = React.useRef(ref);
const combinedRef = useCombinedRefs(ref, innerRef);
return (
<div className="searchContainer">
<input type="text" onKeyDown={props.onKeyDown} ref={combinedRef} />
<button onClick={props.submit} type="submit" value="Submit" className="primaryButton">Search</button>
</div>
)
});
The component on render:
<Search onKeyDown={this.inputKeyDown} ref={this.childRef} />
And replacing
this.tagInput.value = null;
with
this.childRef.current.value = null;