Updated code Initialized constructor and placed filter and loadOptions in class render method. Still showing error saying that this.state.cars.filter is not a function.
import React, { Component } from 'react';
import AsyncSelect from 'react-select/async';
export default class Search extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: null,
cars: []
};
}
componentDidMount() {
fetch(url)
.then(res => {
this.setState(prevState => ({...prevState, cars: res}))
})
}
handleInputChange = (newValue) => {
const inputValue = newValue.replace(/\W/g, '');
this.setState({ inputValue });
return inputValue;
};
render() {
const filterCars = (inputValue) => {
return this.state.cars.filter((i) =>
i.label.toLowerCase().includes(inputValue.toLowerCase())
);
};
const loadOptions = (
inputValue,
callback) => {
setTimeout(() => {
callback(filterCars(inputValue));
}, 1000);
};
return (
<div>
<AsyncSelect
cacheOptions
loadOptions={loadOptions}
defaultOptions
onInputChange={this.handleInputChange}
/>
</div>
);
}
}
Example code of json file that Im fetching data from
[{"make":"KIA","link":"\/images\/image.jpg"},{"make":"BMW","link":"\/images\/image.jpg"}]
There are a couple of issues here. First is that you should declare state inside of a constructor, so instead of declaring state like that, do the following:
constructor(props) {
super(props)
this.state = {inputValue: '', cars: []}
}
Then you need to deal with your state mutations. Whenever you call setState, you are essentially giving it a new object which it sets the state to. You do not reassign the properties, you return a new object.
To resolve this reassignment issue, ES6 has introduced the spread operator which was not specifically designed to deal with mutations but it helps a lot.
Essentially, whenever you want to create a copy of an object, you don't do
let a = b
instead you do
let a = {...b}
With this change, changes on A will not reflect on B. So you make a copy instead of a duplicate.
How you can use this to avoid state mutation?
Whenever you call setState, make sure to first spread the rest of the state accross the new one before making any property changes:
setState(prevState => ({...prevState, cars: res}))
This way, you do not essentially remove the inputValue from your state object which can cause undefined issues.
Back to the main issue, your function filterCars is located outside of your class and in there you are trying to access this.state. Move the filterCars function inside of the class and your error will be resolved but if you don't resolve the mutation issues, it will not work as expected.