update grid by async function - react - reactjs

I have this function - to manage grid and to create it:
export default function CustomizableComponents({ direction }) {
const [rows, setRows] = useState(ComponentDidMount);
const [sortColumns, setSortColumns] = useState([]);
const [selectedRows, setSelectedRows] = useState(() => new Set());
const sortedRows = useMemo(() => {
if (sortColumns.length === 0) return rows;
return [...rows].sort((a, b) => {
for (const sort of sortColumns) {
const comparator = getComparator(sort.columnKey);
const compResult = comparator(a, b);
if (compResult !== 0) {
return sort.direction === 'ASC' ? compResult : -compResult;
}
}
return 0;
});
}, [rows, sortColumns]);
return (
<DataGrid
className="fill-grid"
columns={columns}
rows={sortedRows}
sortColumns={sortColumns}
onSortColumnsChange={setSortColumns}
selectedRows={selectedRows}
onSelectedRowsChange={setSelectedRows}
renderers={{ sortStatus, checkboxFormatter }}
direction={direction}
/>
);
}
And, I have this function (to get the data from server):
async function ComponentDidMount() {
// GET request using fetch with async/await
const response = await fetch('https://localhost:7198/api/FilesDetails/GetListDetails');
const data = await response.json();
for (let i = 1; i < 10; i++) {
rows.push({
id: data[i].name,
name: data[i].name,
startTime: data[i].name,
endTime: data[i].name
});
}
return rows;
}
It reaches the function, and fills the rows,
But the datagrid remains empty and does not fill.
Where am I wrong?
Thanks

Related

fetch data is updated but array and state is not updated

i am woking on weather api and storing perticular data in an array arr but value is not available in arr. also state arrdata is null too.
i tried to not use state but still not getting data in arr . it show reading undefined value.
export default function App() {
const [cityName, setCityName] = useState("delhi");
const [arrData, setArrData] = useState(null);
const getWeatherInfo = async () => {
const url = "https://api.openweathermap.org/data/2.5/forecast";
const api = "4beffc863037e89f0f181d893d1cf79b";
fetch(`${url}?q=${cityName}&units=metric&appid=${api}`)
.then((res) => res.json())
.then((getData) => {
if(getData.list[4].main !== null){
const arr = [];
for (let i = 0; i <= 40; i++) {
if (i % 8 === 0) {
arr.push({
temprature: getData.list[i].main.temp,
Min_temp: getData.list[i].main.temp_min,
Max_temp: getData.list[i].main.temp_max,
date: getData.list[i].dt_txt,
mood: getData.list[i].weather[0].main,
weathermoodIcon: getData.list[i].weather[0].icon,
Humidity: getData.list[i].main.humidity,
});
}}
setArrData(arr);
}});
};
useEffect(() => {
getWeatherInfo()
}, []);
console.log(arrData)
const onInputChange = (e) => {
setCityName(e.target.value);
};
const onSubmitCity = () => {
getWeatherInfo();
};
return (
<>
<Input onChangeValue={onInputChange} onSubmit={onSubmitCity} />
</>
);
}
This seems to be working. Please do not forget to use optional chaining
import {useState, useEffect } from 'react';
export default function App() {
const [cityName, setCityName] = useState("delhi");
const [arrData, setArrData] = useState(null);
const getWeatherInfo = async () => {
const url = "https://api.openweathermap.org/data/2.5/forecast";
const api = "4beffc863037e89f0f181d893d1cf79b";
fetch(`${url}?q=${cityName}&units=metric&appid=${api}`)
.then((res) => res.json())
.then((getData) => {
if(getData.list[40]?.main !== null){
const arr = [];
console.log(getData.list)
for (let i = 0; i <= 4; i++) {
if (i % 8 === 0) {
arr.push({
temprature: getData.list[i]?.main.temp,
Min_temp: getData.list[i]?.main.temp_min,
Max_temp: getData.list[i]?.main.temp_max,
date: getData.list[i]?.dt_txt,
mood: getData.list[i]?.weather[0].main,
weathermoodIcon: getData.list[i]?.weather[0].icon,
Humidity: getData.list[i]?.main.humidity,
});
}}
setArrData(arr);
}});
};
useEffect(() => {
getWeatherInfo();
}, []);
console.log(arrData)
const onInputChange = (e) => {
setCityName(e.target.value);
};
const onSubmitCity = () => {
getWeatherInfo();
};
return (
<>
<input onChange={onInputChange} onSubmit={onSubmitCity} />
<h1> {JSON.stringify(arrData)} </h1>
<button onClick = {onSubmitCity}> Submit </button>
</>
);
}

React - API data only showing if I manually refresh the page

I'm new to React and I created a small admin panel where you can add, edit, remove products. I would like to display 3 products from API when someone opens the app the first time and don't have edited products yet, but this data only shows if I manually refresh the page. I only want to display that if edited product is false, but initially I set edited products to false yet somehow it's not displaying, though I see the data as well as edited is set to false in the console.
Demo
https://react-storeadminpanel.herokuapp.com/
Here is the related code:
const Products = () => {
const {products, setProducts, setAllProducts, allProducts, editedItems, setEditedItems} = useProduct();
useEffect(() => {
async function fetchProducts() {
const res = await axios.get('https://a.nacapi.com/LimeGreen/products/').catch(err => console.log(err));
if(res) {
setProducts(res.data)
setEditedItems(false);
if(allProducts.length === 0 && editedItems === false) setAllProducts(products);
if(allProducts.length === 0 && editedItems === true) setAllProducts(allProducts);
if(allProducts.length > 0) setAllProducts([...allProducts]);
}
return res;
}
fetchProducts();
}, []);
return (
<Wrapper classname="wrapper">
<h1>All Products</h1>
<Cards>
{!!allProducts.length && (
allProducts.map(product => (
<ProductCard name={product.name} description={product.Description} price={product.Price} discount={product.Discount} key={product.uuid}/>
))
)}
</Cards>
</Wrapper>
)
}
The context, where I use LocalStorage
export const ProductContext = React.createContext();
export function useProduct() {
return useContext(ProductContext);
}
export function ProductProvider({children}) {
const [products, setProducts] = useLocalStorage('Api Data', []);
const [addedProduct, setAddedProduct] = useLocalStorage('Added Item', []);
const [allProducts, setAllProducts] = useLocalStorage('All Products', []);
const [editedItems, setEditedItems ] = useLocalStorage('Edited', false);
const [isAdded, setIsAdded] = useState(false);
const value = {
products,
setProducts,
addedProduct,
setAddedProduct,
allProducts,
setAllProducts,
editedItems,
setEditedItems,
isAdded,
setIsAdded,
}
return (
<ProductContext.Provider value={value}>
{children}
</ProductContext.Provider>
)
}
And Code where I set edit products to true
const ProductEdit = () => {
const {allProducts, setAllProducts, setEditedItems} = useProduct();
const [editProductId, setEditProductId] = useState(null);
const [editForm, setEditForm] = useState({
name: "",
Description: "",
Price: "",
Discount: "",
})
const saveEditHandler = (e) => {
e.preventDefault();
const fieldName = e.target.getAttribute("name");
const fieldValue = e.target.value;
const newForm = {...editForm};
newForm[fieldName] = fieldValue;
setEditForm(newForm);
}
const editHandler = (e, product) => {
e.preventDefault();
setEditProductId(product.uuid);
const formValues = {
name: product.Name,
Description: product.Description,
Price: product.Price,
Discount: product.Discount
}
setEditForm(formValues);
}
const submitEditsHandler = (e) => {
e.preventDefault();
const editedProduct = {
name: editForm.Name,
Description: editForm.Description,
Price: editForm.Price,
Discount: editForm.Discount,
uuid: editProductId
}
const newProducts = [...allProducts];
const index = allProducts.findIndex((product) => product.uuid === editProductId);
newProducts[index] = editedProduct;
setAllProducts(newProducts);
setEditedItems(true);
setEditProductId(null);
}
const cancelHandler = () => {
setEditProductId(null);
}
const deleteHandler = (productId) => {
const newProducts = [...allProducts];
const index = allProducts.findIndex((product) => product.uuid === productId);
newProducts.splice(index, 1);
setAllProducts(newProducts);
setEditedItems(true);
};

Why does my function still return a promisse in react native

My function which gets the values is returning a promise which I don't know how to wait for resolve. My failed code:
const [rednderSaves, setRenderSaves] = React.useState([])
const saveRenders = async () => {
var data = await JSON.parse(await AsyncStorage.getItem("connections"))
for (var i = 0; i < data.length; i++) {
data[i].data = await JSON.parse(await data[i].data)
}
setRenderSaves(data)
}
{saveRenders().then(rednderSaves.map(save => {
return <Text key={Date.now()}>{save.name}</Text>
}))}
This overcomplicated thing STILL RETURNS A PROMISE. I have been scratching my head for the last 4 hours, please someone finally help. Thanks in advance
chained then always returns another promise. the proper way would to load your data at useEffect lifecycle correctly.
const [renderSaves, setRenderSaves] = React.useState([])
React.useEffect(() => {
const saveRenders = async () => {
const data = JSON.parse(await AsyncStorage.getItem("connections"))
for (let i = 0; i < data.length; i++) {
data[i].data = JSON.parse(data[i].data)
}
setRenderSaves(data)
}
saveRenders()
}, [])
return (
<>
// ... content
{ renderSaves.map(save => <Text key={Date.now()}>{save.name}</Text>) }
</>
)
try this
const [rednderSaves, setRenderSaves] = React.useState([])
React.useEffect(()=>{
saveRenders()
},[])
const saveRenders = async () => {
var data = await JSON.parse(await AsyncStorage.getItem("connections"))
for (var i = 0; i < data.length; i++) {
data[i].data = await JSON.parse(await data[i].data)
}
setRenderSaves(data)
}
return (
<>
{
rednderSaves.length?rednderSaves.map(save => (
<Text key={Date.now()}>{save.name}</Text>
)):
null
}
</>
)

useState not updating the state

I'm trying to filter users with input search inside the function searchByName.
I manage to get the right result in copyUsersvariable but unfortunately it does not reflect the change inside the state.
Forgot to mention, using bare React-App with hooks and typescript.
For example, i write 'p' in the input and recieve the right filtered array in copyUsers variable but then i push it into the state it does not update.
Attaching screenshot for understanding the situation better:
what i have tried instead setFilteredUsers(copyUsers):
setFilteredUsers(() => [...filteredUsers, copyUsers]);
setFilteredUsers(() => copyUsers);
main component:
const { value } = useSelector(({ test }: any) => test);
const [users, setUsers] = useState<Users>([]);
const [filteredUsers, setFilteredUsers] = useState<Users>([]);
const [searchNameValue, setSearchNameValue] = useState<string>("");
const [selectedUser, setSelectedUser] = useState<User>();
const [searchOrderBy, setSearchOrderBy] = useState<string>("");
const dispatch = useDispatch();
useEffect(() => {
const get = async () => {
const response = await ApiTest.testGet();
setUsers(response);
setSearchOrderBy("desc");
};
get();
}, []);
useEffect(() => {
searchByName();
setNewOrder();
}, [searchOrderBy]);
useEffect(() => {
console.log('search value changed!', searchNameValue);
searchByName();
setNewOrder()
}, [searchNameValue]);
const setNewOrder = () => {
if (users.length) {
let copyUsers = JSON.parse(
JSON.stringify(filteredUsers.length ? filteredUsers : users)
);
switch (searchOrderBy) {
case "desc":
copyUsers.sort((a: any, b: any) => {
if (a.id > b.id) {
return -1;
}
if (b.id > a.id) {
return 1;
}
return 0;
});
break;
case "asc":
copyUsers.sort((a: any, b: any) => {
if (b.id > a.id) {
return -1;
}
if (a.id > b.id) {
return 1;
}
return 0;
});
break;
default:
break;
}
filteredUsers.length ? setFilteredUsers(copyUsers) : setUsers(copyUsers);
}
};
const searchByName = () => {
if (searchNameValue) {
let copyUsers = JSON.parse(JSON.stringify(users));
copyUsers = copyUsers.filter((user: User) => {
return user.name
.toLocaleLowerCase()
.includes(searchNameValue.toLocaleLowerCase());
});
console.log("copyUsers =", copyUsers);
setFilteredUsers(copyUsers);
console.log("filteredUsers =", filteredUsers);
}
};
const UserCards =
!!users.length &&
(searchNameValue ? filteredUsers : users).map(user => {
return (
<UserCard
selectedUser={selectedUser}
setSelectedUser={(user: User) => setSelectedUser(user)}
user={user}
/>
);
});
return (
<div>
<FilterBar
searchOrderBy={searchOrderBy}
searchSetOrderBy={(value: string) => setSearchOrderBy(value)}
setSearchNameValue={(value: string) => setSearchNameValue(value)}
searchNameValue={searchNameValue}
/>
<div style={{ display: "flex", flexFlow: "wrap" }}>{UserCards}</div>
</div>
);

how can i call method dynamically in react hooks

In my React hooks I defined two functions for setting variables:
setProjectMiddleCode
and setProjectToolCode.
I hope to call this two method in my react hooks to avoid duplicate code.
I would like to do it like this:
//variable define
let data;
let index = res.data.indexOf(res.code.value);
//call dynamic
if(some state ==='A'){
data= "setProjectMiddleCode"
}else{
data = "setProjectToolCode"
}
if (index < 0) {
this[data](res.data.concat(res.code.value));
} else {
this[data](res.data.filter((_, i) => i !== index));
}
My current code:
const [projectMiddleCode, setProjectMiddleCode] = useState([]);
const [projectToolCode, setProjectToolCode] = useState([]);
const ProjectWrite = memo(({}) => {
let component;
const dispatch = useDispatch();
const [projectMiddleCode, setProjectMiddleCode] = useState([]);
const [projectToolCode, setProjectToolCode] = useState([]);
const callbackFromChild = useCallback(
res => () => {
let index = res.data.indexOf(res.code.value);
if (res.codeName === 'PROJECT_MIDDLE_CODE') {
if (index < 0) {
setProjectMiddleCode(res.data.concat(res.code.value));
} else {
setProjectMiddleCode(res.data.filter((_, i) => i !== index));
}
} else if (res.codeName === 'TOOL_LIST') {
if (index < 0) {
setProjectToolCode(res.data.concat(res.code.value));
} else {
setProjectToolCode(res.data.filter((_, i) => i !== index));
}
}
},
[]
);
One way to do this is to create a map of res.codeName to your functions:
const { codeName, code, data } = res;
const index = data.indexOf(code.value);
const funcMap = {
PROJECT_MIDDLE_CODE: setProjectMiddleCode,
TOOL_LIST: setProjectToolCode
}
const newData = index < 0 ? data.concat(code.value) : data.filter((_, i) => i !== index);
const func = funcMap[codeName];
func(newData);

Resources