react-awesome-query-builder empty select when click outside select - reactjs

I use asyncFetch and I select value from SelectWiget , after any click outside make empty value this select.
I use next config for fields
products: {
type: '!struct',
label: 'Products',
subfields: {
title: {
type: 'select',
label: 'Name',
fieldSettings: {
asyncFetch: async (search, offset) => {
const toSearch = _.isEmpty(search) ? 'null' : search;
const prodApi = (await axios.get(`http://localhost:8002/api/products/1/${toSearch}?offset=${offset}`, { headers: authHeader() }));
const productsValues = prodApi.data.data.map(
product => ({
title: product.title,
value: product.id
})
)
return {
values: productsValues,
hasMore: true,
}
},
useAsyncSearch: true,
useLoadMore: true,
forceAsyncSearch: false,
allowCustomValues: false
}
},
Another error is when i select some value the asyncFetch is call again.
Is this a bug in that package or i have missing some configuration ?
the package what i use is react-awesome-query-builder

the value from result of function async need to be string, so function is like :
asyncFetch: async (search, offset) => {
const toSearch = _.isEmpty(search) ? 'null' : search;
const prodApi = (await axios.get(`http://localhost:8002/api/products/1/${toSearch}?offset=${offset}`, { headers: authHeader() }));
const productsValues = prodApi.data.data.map(
product => ({
title: product.title,
value: product.id.toString(),
})
)
return {
values: productsValues,
hasMore: true,
}
}

Related

How to recall getServerSideProps value without reload the page when the value changed

I want to change languageId value without the page reloading. When the languageId value changes the title of products is changed.
export const getServerSideProps = async ({ req, res, query }) => {
try {
const languageId = getCookie('appLanguageId', { req, res })
const countryid = getCookie('countryId', { req, res })
const appLanguage = getCookie('appLanguage', { req, res })
const { id, page, brandId } = query
var fields = [{ condition: 'contains', value: id, dataField: 'categoryPath' }];
// FILTERS
let flag = true;
if (query.brandIds) {
flag = false;
fields.push({ condition: "equal", value: query.brandIds, dataField: 'brandId' });
}
if (query.priceStart) {
flag = false;
fields.push({ condition: ">=", value: query.priceStart, dataField: 'listPrice' });
}
if (query.priceEnd) {
flag = false;
fields.push({ condition: "<=", value: query.priceEnd, dataField: 'listPrice' });
}
const response = await axios.post(urlHelper + '/wapi/v1/product/listSearch',
{
filter: {
fields,
page: { number: page || 1, size: 20, },
}
},
{
headers: { languageId, countryid }
}
);
//
const products = response?.data;
const filterOptions = (await axios.get(`${urlHelper}/wapi/v1/category/filterOptions/${id}`)).data
return {
props: {
products: products?.data || [],
totalCount: products?.totalCount || 0,
filterOptions: filterOptions,
filterObj: {
brandIds: query.brandIds ? query.brandIds : null,
priceStart: query.priceStart ? query.priceStart : null,
priceEnd: query.priceEnd ? query.priceEnd : null,
isAllNull: flag
},
loader: false
},
};
};
I use getServerSideProps. How can I fix it? I have to access product titles correctly when the language change.

useQuery isn't rendering/fetching multiple times on the local machine, but in production, it's working

When I run my react-project on my local machine, useQuery doesn't fetch data multiple-time, it renders data only on first-time loading.
const [todayAttendance, setTodayAttendance] = React.useState([]);
const {
data: allAttendance,
isLoading: attendanceIsLoading,
isError: attendanceIsError,
} = useQuery(
["todaysAbsent", branchId],
async () =>
myAxios(`/all_attendance/${moment().format("MM")}/${moment().format(
"YYYY"
)}/?branch_id=${branchId ?? ""}`
),
{
onSuccess: (e) => {
setTodayAttendance([]);
Object.values(e.data).filter(
({ attendance, name, position, information_user }, i) =>
setTodayAttendance((prev) => [
...prev,
{
attendance: attendance[`${moment().format("YYYY-MM-DD")}`],
id: i,
status:
attendance[`${moment().format("YYYY-MM-DD")}`]["status"],
name: name,
position: position,
information_user: information_user,
},
])
);
},
}

How to I pass a filters variable to useInfiniteQuery with pageParam?

I'm trying to pass the queryKey variable alongside the pageParam in useInfiniteQuery? I've tried for a while but:
Cannot get the page data
In some cases, the data is rendered repeatedly.
How should I pass the variables?
export const fetchInfiniteVariants = async (
filters = {},
{ pageParam = 0 }
) => {
const records = await axios.get(baseURL, {
headers: authHeader,
params: {
pageSize: 24,
offset: pageParam,
fields: [
"name",
"packshot",
"packshot_size",
"brand_logo",
"price",
"slug",
],
// filterByFormula: `({validated} = 1)`,
filterByFormula: `(${filterByFields(filters)})`,
"sort[0][field]": "priority",
"sort[0][direction]": "asc",
},
})
return records
}
export const useInfiniteVariantsQuery = (
initialRecords,
offset,
filters = { brand: "HAY" }
) => {
const infiniteVariantsQuery = useInfiniteQuery(
["infiniteVariants", filters],
() => fetchInfiniteVariants(filters),
{
initialStale: true,
staleTime: 6000,
getNextPageParam: (lastPage, pages) => lastPage.data.offset,
}
)
return {
...infiniteVariantsQuery,
}
}
The queryFn you're passing to useInfiniteQuery has request context as a parameter to that callback, as documented on the useInfiniteQuery page:
Receives a QueryFunctionContext object with the following variables:
queryKey: EnsuredQueryKey: the queryKey, guaranteed to be an Array
pageParam: unknown | undefined
You can destructure and retrieve your queryKey from that, as below:
export const useInfiniteVariantsQuery = (
initialRecords,
offset,
filters = { brand: "HAY" }
) => {
const infiniteVariantsQuery = useInfiniteQuery(
["infiniteVariants", filters],
({ queryKey, pageParam }) => fetchInfiniteVariants(queryKey[1], pageParam),
{
initialStale: true,
staleTime: 6000,
getNextPageParam: (lastPage, pages) => lastPage.data.offset,
}
)
return {
...infiniteVariantsQuery,
}
}

changing some specific value react usestate

const [checkedHealth, setCheckedHealth] = useState(checkboxHealthLabels);
const handleChangeHealth = (event) => {
setCheckedHealth([
...checkedHealth,
[event.target.name]: event.target.checked,
]);
};
and checkboxHealthLabels file :
export const checkboxHealthLabels = [
{ name: "Alcohol-Free", checked: false },
{ name: "Celery-Free", checked: false },
{ name: "Dairy-Free", checked: false },
];
now I want to change just one object for example : { name: "Alcohol-Free", checked: false },
and other values have to stay same. How can I do that?
Find the index of the object in the array with the same name, then toggle it as needed:
const handleChangeHealth = ({ target }) => {
const { name } = target;
const index = checkedHealth.findIndex(obj => obj.name === name);
setCheckedHealth([
...checkedHealth.slice(0, index),
{ name, checked: target.checked },
...checkedHealth.slice(index + 1)
]);
};
You could also consider having the state be an object (with the names being the object properties) instead of an array, it might be easier.

map over multiple arrays and only return specific ones

I currently have an axios get request that fetches data from a nasa API and returns it into a list of arrays.
getDataHandler= () => {
axios.get('https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=DEMO_KEY',)
.then((response) => {
const restructuredData = response.data.near_earth_objects.map(
({ name, estimated_diameter, close_approach_data }) => {
const close_approaches = close_approach_data && close_approach_data.length
? close_approach_data.map(({ orbiting_body }) => orbiting_body)
: ["no orbited planet"] // If the array doesn't exist, just use an empty array.
return [
name,
estimated_diameter.kilometers.estimated_diameter_min,
estimated_diameter.kilometers.estimated_diameter_max,
close_approaches[0]
]
})
})
It returns a list of arrays that look like this:
0: (4) ["21277 (1996 TO5)", 1.6016033798, 3.5812940302, "Mars"]
1: (4) ["162038 (1996 DH)", 1.2721987854, 2.844722965, "no orbited planet"]
2: (4) ["189058 (2000 UT16)", 1.332155667, 2.978790628, "Earth"]
3: (4) ["276274 (2002 SS41)", 0.9650614696, 2.1579430484, "Earth"]
4: (4) ["322913 (2002 CM1)", 1.214940408, 2.7166893409, "Jupiter"]
5: (4) ["435730 (2008 UK90)", 0.4411182, 0.9863702813, "no orbited planet"]
Then it gets the list and setState it.
Problem is I have a dropDown menu to only show data from specific planets. So I was wondering if it's possible to map of it again and only keep the ones that are equal to the current selected planet.
And if no planets are selected return all of them.
code i have so far
class MainPage extends Component {
state = {
data: [['name', 'min estimated diameter', 'max estimated diameter', { role: "planet" }]],
dropDownOptions: [
{ value: 'all', label: 'All' },
{ value: 'earth', label: 'Earth' },
{ value: 'mars', label: 'Mars' },
{ value: 'mercury', label: 'Mercury' },
{ value: 'venus', label: 'Venus' },
{ value: 'saturn', label: 'Saturn' },
{ value: 'jupiter', label: 'Jupiter' },
{ value: 'no orbited planet', label: 'No orbited planet'}
],
SelectedDropDownOption: { value: 'all', label: 'All' },
}
componentDidMount() {
this.getDataHandler()
}
getDataHandler= () => {
axios.get('https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=DEMO_KEY',)
.then((response) => {
const restructuredData = response.data.near_earth_objects.map(
({ name, estimated_diameter, close_approach_data }) => {
const close_approaches = close_approach_data &&
close_approach_data.length
? close_approach_data.map(({ orbiting_body }) => orbiting_body)
: ["no orbited planet"]
return [
name,
estimated_diameter.kilometers.estimated_diameter_min,
estimated_diameter.kilometers.estimated_diameter_max,
close_approaches[0]
]
}
)
const joined = this.state.data.concat(restructuredData)
this.setState({ data: joined })
})
.catch(function (error) {
console.log(error);
})
}
DropDownChangeHandler= (SelectedDropDownOption) => {
console.log("hello")
this.setState({SelectedDropDownOption});
}
render () {
console.log(this.state.data)
console.log(this.state.SelectedDropDownOption)
console.log(this.state.SelectedDropDownOption.value)
return (
<React.Fragment>
<DropDown options={this.state.dropDownOptions} onChange={this.getPlanetInformation}/>
<Chart chartData={this.state.data} />
</React.Fragment>
);
}
}
export default MainPage;
You can use filter method to achieve your goal. You loop over every sub array and you keep only those which includes the require planet name passed as function parameter.
const arrayList = [["21277 (1996 TO5)", 1.6016033798, 3.5812940302, "Mars"], ["162038 (1996 DH)", 1.2721987854, 2.844722965, "no orbited planet"], ["189058 (2000 UT16)", 1.332155667, 2.978790628, "Earth"],["276274 (2002 SS41)", 0.9650614696, 2.1579430484, "Earth"], ["322913 (2002 CM1)", 1.214940408, 2.7166893409, "Jupiter"]]
const getPlanetInformation = (planet) => {
const information = arrayList.filter(item => item.includes(planet))
console.log(information)
return information.length ? information : arrayList
}
If there is no planet selected from your dropdown value or the selected doesn't exists inside your array, you can just return the initial value.

Resources