When using the parameter defaultValue of the component Select no values is found.
<Select
mode='multiple'
allowClear
style={{ width: '100%' }}
placeholder='Sélectionner...'
onChange={setValue}
onSelect={handleSelect}
defaultValue={dataChecked}
onDeselect={handleDeselect}
>
{
dataType.map((v) => (
<Option key={v.valueKey} value={v.valueKey}>
<img className='img-step' src={`http://localhost:2023/api/pictures/${props.typeUrlPicture}/${v.picture}`} alt={v.picture}/>
{" "}{v.label}
</Option>
))
}
</Select>
Here I use dataChecked as a variable. dataChecked is a array of value.
const [ data, setData ] = useState([])
const dataType = data.map((l)=> ({ label: l.name, value: l.picture, valueKey: l.id, picture: l.picture }))
const [ value, setValue ] = useState([])
const [ dataChecked, setDataChecked ] = useState([])
useEffect(() => {
fetch(`${baseUrl}/properties?type=${props.type}`)
.then((res) => res.json())
.then((data) => {
setData(data)
})
fetch(`${baseUrl}/steps/${props.idBdd}`)
.then((res) => res.json())
.then((data) => {
data.properties.filter(d => d.type === props.type).map((d) => (
setDataChecked(current => [...current, d.id])
))
})
return () => {
setData([])
setDataChecked([])
}
}, [props.type, props.idBdd])
The values of my Options are indeed integers like the values of my dataChecked array.
If I replace dataChecked with an array : [1,9]. I get my initial values. And
when I console.log(dataChecked) I get an array of [1,9] for example but my component gets no initial value.
There are two ways, you can try.
<!-- 1. Use value prop -->
<Select mode="multiple" value={defaultValue}></Select>
<!-- 2. Set defaultValue to key -->
<Select mode="multiple" key={defaultValue.join(',')}></Select>
Related
My sorting is working but sometimes my data doesnot change as I select the option no change occurs , I guess I am not using useEffect correctly So I want what am I doing wrong , I am very confused
const { data: property, isFetching, refetch } = useQuery(['PropertySearch', startDate, endDate, where, adultCount, childCount], propertyAvaibility, {
retry: false,
enabled: !!data
})
useEffect(() => {
const sortArray = type => {
const types = {
number_of_bars: 'number_of_bars',
starting_price: 'starting_price',
};
const sortProperty = types[type];
const sorted = property?.sort((a, b) => b[sortProperty] - a[sortProperty]);
setData(sorted);
};
sortArray(sortType);
}, [sortType]);
<select onChange={(e) => setSortType(e.target.value)} className="form-control">
<option value="number_of_bars">number_of_bars</option>
<option value="starting_price">starting_price</option>
</select>
{
property?.map((item) => (
<PropertyCard
key={item?.id}
title={item?.title}
image={item?.cover_image?.url}
location={item.address}
displayFooter={false}
displayButton={false}
rating={true}
item={item}
type={item?.brand_name}
link="property">
{item?.description?.slice(0, 150)}
</PropertyCard>
))
}
I think your problem is you're using property?.map which is always referred to your original list.
For a possible fix, you could modify it to data?.map which is your sorted list.
And you also need to set a default value for data
const [data, setData] = useState(property); //`property` is from your fetched data
Full change can be
const { data: property, isFetching, refetch } = useQuery(['PropertySearch', startDate, endDate, where, adultCount, childCount], propertyAvaibility, {
retry: false,
enabled: !!data
})
const [data, setData] = useState(property); //set `property` as your default data
const [sortType, setSortType] = useState('rating');
useEffect(() => {
const sortArray = type => {
const types = {
number_of_bars: 'number_of_bars',
starting_price: 'starting_price',
};
const sortProperty = types[type];
const sorted = property?.sort((a, b) => b[sortProperty] - a[sortProperty]);
setData(sorted);
};
sortArray(sortType);
}, [sortType]);
const displayedData = data?.length ? data : property //check if data is available
<select onChange={(e) => setSortType(e.target.value)} className="form-control">
<option value="number_of_bars">number_of_bars</option>
<option value="starting_price">starting_price</option>
</select>
{
displayedData?.map((item) => ( //the main change is here
<PropertyCard
key={item?.id}
title={item?.title}
image={item?.cover_image?.url}
location={item.address}
displayFooter={false}
displayButton={false}
rating={true}
item={item}
type={item?.brand_name}
link="property">
{item?.description?.slice(0, 150)}
</PropertyCard>
))
}
I am adding all is needed to create a post, but am getting an error message saying "Facility must exist."
For some reason, the facility_id is capturing the name of the facility and not the ID.
I am setting state for facilities, and mapping / filtering for my dropdown. Please see below:
function AddPostForm({ posts, handlePost})
{
const [facilities, setFacilities] = useState ([])
const [procedures, setProcedures] = useState ([])
const uniques = procedures.map(procedure => procedure.procedure)
.filter((value, index, self) => self.indexOf(value) === index )
// console.log("unique procedures:", uniques)
const uniqFacility = facilities.map(facility => facility.name).filter((value,index, self) => self.indexOf(value) === index)
useEffect(() => {
fetch(`/posts/${procedures}`)
.then((r) => r.json())
.then(setProcedures);
}, []);
useEffect(() => {
fetch("/facilities")
.then((r) => r.json())
.then(setFacilities);
}, []);
const [formData, setFormData] = useState({
facility_id: "",
procedure:'',
date_of_procedure:'',
date_of_invoice:'',
patient_cost: "",
insurance_cost: "",
comments: ""
})
const { id } = useParams();
function handleChange(event) {
setFormData({
...formData,[event.target.name]: event.target.value,
});
}
function handleSubmit(event) {
event.preventDefault();
handlePost(formData)
return (
<div >
<form onSubmit={handleSubmit}>
<label htmlFor="facility_id">Facility:</label>
<select
id="facility_id"
name="facility_id"
value={formData.facility_id}
onChange={handleChange} >
<option value="">Select Facility</option>
{uniqFacility.map((facility) => (
<option key={facility.id} value={facility.name}>
{facility}
</option>
))}
</select>
</form>
</div>
);
}
export default AddPostForm;
When I check params in the byebug I see facility_id=>"Name of Facility", and get an error message saying that Facility must exist. I tried adjusting the map / filter function to ...facility => facility.id).filter ... , which ends up giving me the facility_id and creates the post as if the name of the entity was its id.
I think I need to adjust the map/filter formula, but I do not know how. Appreciate if someone help me out here.
I'm trying to filter through the RandomUser api to display either males or females. My current issue is that I can't display the filtered data like I did the original data.
Here's my current code:
const [data, setData] = useState('');
const [gender, setGender] = useState('');
useEffect(() => {
fetch(`https://randomuser.me/api/?results=500`)
.then(response => response.json())
.then(setData);
}, [])
const FilterData = () => {
if(gender) {
var searchedResult
searchedResult = data.results.filter(
(e) => e.gender === gender
);
console.log(searchedResult)
console.log(gender)
setData([searchedResult])
}
}
if(data.results){
return (
<div>
<div>
<select name="Gender" onChange={(e) => setGender(e.target.value)}>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
<button onChange={FilterData()}></button>
</div>
<ul>
{data.results.map(results => (
<li key={results}>
<p>{results.name.first} {results.name.last}</p>
<img src={results.picture.medium}></img>
</li>
))}
</ul>
</div>
)
}
else{
return(
<div>loading...</div>
)
}
}
I think my issue applies to how I originally setup my html with my if/else statement leading to the html constantly showing 'loading...' if I don't have data.results but I'm not too sure on how I'd apply that to my new filtered array
The way I would approach this is by setting your fetched data in state.
Then create another state called something like filteredData as to not mutate your fetched data. Once you filter the data, you want a way to go back to the original data to filter it differently.
On selection of a gender, filter through your fetched data and set filteredData as an array of people objects with your selected gender.
If filteredData exists (which gets set by a useEffect when gender is changed), map over that to display your data. If there is no gender selected (and therefore, no filteredData, map over data.results array.
Check out this jsfiddle
The issue is that when you initially call setData you're passing the full response, but when you call it in FilterData you are passing in a single element array. And then it doesn't re-render because you are testing for data.results which no longer exists.
Try this...
const [data, setData] = useState(null);
const [gender, setGender] = useState('');
useEffect(() => {
fetch(`https://randomuser.me/api/?results=10`)
.then(response => response.json())
.then((data) => {
setData(data.results)
});
}, [])
const FilterData = () => {
if (gender) {
var searchedResult
searchedResult = data.filter(
(e) => e.gender === gender
);
console.log(searchedResult)
console.log(gender)
setData(searchedResult)
}
}
if (data) {
return (
<div>
<div>
<select name="Gender" onChange={(e) => setGender(e.target.value)}>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
<button onClick={FilterData}></button>
</div>
<ul>
{data.map((results, idx) => (
<li key={idx}>
<p>{results.name.first} {results.name.last}</p>
</li>
))}
</ul>
</div>
)
} else {
return (
<div>loading...</div>
)
}
I am very new to Reactjs, I am working on retrieving some data in order to display it, everything gets displayed however, when I filter there is an error that comes up "Cannot read property 'filter' of undefined", after debugging I found out that dataList is returning with undefined when typing anything in the search bar.
Appreciate your assistance.
function App() {
var dataList;
useEffect(() => {
// http get request
const headers = {
'Content-Type': 'application/json',
'Authorization': '***********************',
'UserAddressId': ****,
'StoreId': *
}
axios.get('https://app.markitworld.com/api/v2/user/products', {
headers: headers
})
.then((response) => {
dataList = response.data.data.products
setData(dataList)
})
.catch((error) => {
console.log(error)
})
}, []);
const [searchText, setSearchText] = useState([]);
const [data, setData] = useState(dataList);
// exclude column list from filter
const excludeColumns = ["id"];
// handle change event of search input
const handleChange = value => {
setSearchText(value);
filterData(value);
};
// filter records by search text
const filterData = (value) => {
console.log("dataList", dataList)
const lowercasedValue = value.toLowerCase().trim();
if (lowercasedValue === "") setData(dataList);
else {
const filteredData = dataList.filter(item => {
return Object.keys(item).some(key =>
excludeColumns.includes(key) ? false :
item[key].toString().toLowerCase().includes(lowercasedValue)
);
});
setData(filteredData);
}
}
return (
<div className="App">
Search: <input
style={{ marginLeft: 5 }}
type="text"
placeholder="Type to search..."
value={searchText}
onChange={e => handleChange(e.target.value)}
/>
<div className="box-container">
{data && data.length > 0 ? data.map((d, i) => {
return <div key={i} className="box">
<b>Title: </b>{d.title}<br />
<b>Brand Name: </b>{d.brand_name}<br />
<b>Price: </b>{d.price}<br />
<b>Status: </b>{d.status}<br />
</div>
}) : "Loading..."}
<div className="clearboth"></div>
{data && data.length === 0 && <span>No records found to display!</span>}
</div>
</div>
);
}
export default App;
You're mixing up a stateful data variable with a separate non-stateful, local dataList variable. The dataList only gets assigned to inside the axios.get, so it's not defined on subsequent renders; the setData(dataList) puts it into the stateful data, but the dataList on subsequent renders remains undefined.
To make things easier to understand, remove the dataList variable entirely, and just use the stateful data.
You also probably don't want to discard the existing data when the user types something in - instead, figure out what items should be displayed while rendering; rework the filterData so that its logic is only carried out while returning the JSX.
const [searchText, setSearchText] = useState([]);
const [data, setData] = useState([]);
useEffect(() => {
// http get request
const headers = {
'Content-Type': 'application/json',
'Authorization': '***********************',
'UserAddressId': ****,
'StoreId': *
}
axios.get('https://app.markitworld.com/api/v2/user/products', {
headers: headers
})
.then((response) => {
setData(response.data.data.products);
})
.catch((error) => {
console.log(error)
})
}, []);
// handle change event of search input
const handleChange = value => {
setSearchText(value);
};
// filter records by search text
const filterData = () => {
const lowercasedValue = searchText.toLowerCase().trim();
return lowercasedValue === ""
? data
: data.filter(
item => Object.keys(item).some(
key => excludeColumns.includes(key) ? false :
item[key].toString().toLowerCase().includes(lowercasedValue)
)
);
}
And change
{data && data.length > 0 ? data.map((d, i) => {
to
{filterData().map((d, i) => {
Your searchText should also be text, not an array: this
const [searchText, setSearchText] = useState([]);
should be
const [searchText, setSearchText] = useState('');
First of all, you don't need to maintain an additional non-state variable dataList as the local state data would serve the purpose.
API Call Code:
You should directly store the response from API after null checks satisfy.
useEffect(() => {
const headers = {
// key value pairs go here
};
// http request
axios.get(endPoint, {
headers,
})
.then((response) => {
// set data directly null checks
setData(response.data.data.products);
})
.catch((error) => {
console.log(error);
});
}, []);
Filteration Code
Use useCallback hook which would return a memoized version of the callback, unless the value of data changes.
const filterData = useCallback((value) => {
console.log('data', data);
// rest of code
}, [data]);
{ _id: 5d8b8,
given_name: 'Abi',
family_name: 'Abi',
email: 'AAA#jwt.org',
password:'password'
}
I have this data and I want to get only email.
const url = 'http://localhost:9098/api/users'
const [users, setUsers] = useState([])
useEffect(() => {
axios.get(url).then(json => setUsers(json.data))
}, [])
const getEmail = () => {
return users.map(user => {
return (
<option> {user.email} </option>
)
})
}
<select onChange={handleAddMessage}
value={message.sender}
name="sender" id="sender"required>
<option>{getEmail()} </option>
</select>
This is how I am trying to do it .I need an easy way to extract email from this data into
I think that the value attribute has to be inside the option tag.As i can see you are rendering an option tag inside an option tag because the getEmail is returning a option tag:
<option>{getEmail()} </option>
So the approcach that i came up is to make a method that renders the options based on your list:
this.renderEmails = ( ) => {
let optionList = users.map(user => {
return (
<option value={ user.email }> {user.email} </option>
)
})
return optionList
};
And in your render method:
<select onChange={handleAddMessage}
name="sender" id="sender"required>
{ this.renderEmails() }
</select>
Extract the email when you get the data. Itterate through the data using forEach and store it to a variable and finally set it to the users-state
Later you can use users.map() to display the email ID
const url = 'http://localhost:9098/api/users';
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get(url).then(json => {
let usersResponse = []; json.data.forEach((data) => {
usersResponse.push(data.email);
});
setUsers(usersResponse)
})
}, []);
< select
onChange = { handleAddMessage }
value = { message.sender }
name = "sender" id = "sender" required
>
{
users.map((email) => {
<option>{email} </option>
})
}
</select >