I am trying to build a search box. However, when I want to set the state when something is typed in, the box just simply doesn't let me type in anything.
This is the class which calls the component of search box
export default class Tagsearch extends Component {
constructor(props) {
super(props);
this.state = {
hitsDisplay:false,
inputContent:"",
tags:[]
};
}
openDisplay = () => {
console.log("open")
// this.setState({ hitsDisplay: true })
}
closeDisplay = () => {
console.log("close")
// this.setState({ hitsDisplay: false })
}
render() {
let inputTags = (
this.state.tags.map((tag, i) =>
<li key={i} style={styles.items}>
{tag}
<button onClick={() => this.handleRemoveItem(i)}>
(x)
</button>
</li>
)
)
let result = (
<div className="container-fluid" id="results">
</div>
)
if (this.state.hitsDisplay) {
result = (
<div className="container-fluid" id="results">
<div className="rows">
<MyHits handleSelect={this.handleSelect}/>
</div>
<div className="rows">
<Pagination />
</div>
</div>
)
}
return (
<InstantSearch
appId="*******"
apiKey="***********************"
indexName="tags"
>
{inputTags}
<SearchBox
connectSearchBox={connectSearchBox}
openDisplay={this.openDisplay}
closeDisplay={this.closeDisplay}
/>
{result}
</InstantSearch>
)
}
}
The following is the search box component
const SearchBox = props => {
let {
connectSearchBox,
openDisplay,
closeDisplay
} = props;
const CustomSearchBox = connectSearchBox(({ currentRefinement, refine }) => {
const handleChange = (e, refine) => {
refine(e.target.value)
// console.log(e.target.value)
if (e.target.value !== "") {
openDisplay();
} else {
closeDisplay();
}
}
return (
<label>
<ul style={styles.container}>
<input
style={styles.input}
type="text"
value={currentRefinement}
onChange={e => handleChange(e, refine)}
/>
</ul>
</label>
)
})
return (
<CustomSearchBox />
)
}
export default SearchBox;
If I comment the two setStates in open & closeDisplay, It work fine, it prints out open and close accordingly. However, once I enable setState, the input box simply doesn't allow me to type in anything.
Any help is appreciated.
Your code is incorrectly written. connectSearchBox
is meant to wire up a component to the Algolia api. It's a one time setup on a component definition. It returns a higher order component that wraps the given component with api features. You can see the source code here. By putting your custom SearchBox inside the SearchBox function, you are causing the component to be rebuilt and reconnected on each render() cycle, thereby not preserving state. This is why as soon as you setState
your search text disappears.
import { connectSearchBox } from 'react-instantsearch-dom';
const CustomSearchBox = ({ currentRefinement, refine, openDisplay, closeDisplay, ...props }) => {
const handleChange = (e, refine) => {
refine(e.target.value)
if (e.target.value !== "")
openDisplay();
else
closeDisplay();
}
return (
<label>
<ul style={styles.container}>
<input
style={styles.input}
type="text"
value={currentRefinement}
onChange={e => handleChange(e, refine)}
/>
</ul>
</label>
)
})
export default connectSearchBox(CustomSearchBox);
Usage
import CustomSearchBox from './CustomSearchBox'
...
<CustomSearchBox
openDisplay={this.openDisplay}
closeDisplay={this.closeDisplay}
/>
Usage example from the docs. I think what you were trying to achieve was to pass props down to your component but the connectSearchBox
already guarantees that any props you pass to the HOC also gets passed down to the your custom search box. Line 335