I want to create a copy of an array from an api to avoid using "data?.map", in order to be able to sort it later in a table. my use fetch hook:
import { useEffect, useState } from "react";
import axios from "axios";
import { BASE_URL } from "../constants/Constants";
const useFetchData = (url: string) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
const options = {
method: "GET",
url: `${BASE_URL}${url}`,
};
axios
.request(options)
.then((response) => {
setData(response.data);
})
.catch((error) => {
setError(error);
console.error(error);
})
.finally(() => {
setLoading(false);
});
}, [url]);
return { data, loading, error };
};
export default useFetchData;
my Table component:
const { data, loading, error } = useFetchData(SPOT_URL);
const [searchTerm, setSearchTerm] = useState("");
// Table data that displays all the entries or the ones that have the value of the name or
// country inside the SearchInput component
const tableData = data?.filter(
(val: { country: string; name: string }) =>
(searchTerm === "" && val) ||
(val.country.toLowerCase().includes(searchTerm.toLowerCase()) && val) ||
(val.name.toLowerCase().includes(searchTerm.toLowerCase()) && val)
);
...
// After the tableData function is complete, the table rows are generated
const dashboardTableContent = tableData?.map(
(item:) => (
<tr key={item.id}>
<td>{item.name}</td>
<td>{item.country}</td>
<td>{item.lat}</td>
<td>{item.long}</td>
<td>{item.probability}%</td>
<td>{item.month}</td>
</tr>
)
);
...
return (<tbody>{dashboardTableContent}</tbody>)
Is there a way to avoid using the question mark and start using just "data" ? What I am trying to do is a sortable table ascending descending like in this link https://www.smashingmagazine.com/2020/03/sortable-tables-react/ In this link is a spread operator, which I can't use in my code because I don't have the array in the begging and it renders a white page.
CodePudding user response:
If all you want is to avoid the question mark, you can just do
const [data, setData] = useState([]);
Instead of
const [data, setData] = useState(null);
You will get an empty array from the start
CodePudding user response:
Maybe I am wrong, but I will try to help you based on what I have understood reading your question.
If you want to make a copy of an array, you can create a new one, and push everything into it, like this:
const newArray = [];
this.newArray.push(...oldArray);
Now, you can manipulate however you want your new array.
EDIT: I answered before you edited your question, so you can't use my method. Or maybe you can make it asynchronous.
CodePudding user response:
you can try declaring data as an empty array in its initial state.
const [data, setData] = useState([]);
this is one way you can avoid the data?.map later since its initial value is already an empty array and javascript won't complain if the data is null
CodePudding user response:
The optional chaining operator [?.][1]
is a guard against a potentially undefined object whose property you want to access. In your case, data
will be undefined until axios' fetch operation completes and so data.filter
would throw an error.
To solve this you need to decide how you want the component to behave before data
is defined, while the page is still loading. Some options:
- Pretend the table is empty and let more data come in later and update the table. You can do this by
const tableData = data ?? []
and then build your table on thetableData
. - Don't render the table until data is loaded. If it is not, render something like
loading
instead.
Regardless of approach, you have to handle the case that data
is undefined and show your users something reasonable until the data is available.