For a project, I am getting multiple objects that all contain specific football match details, so I filter the matches by matchday but I keep getting an empty array on my first render, and then when I leave the tab and come back it then renders the objects I need, how do I get it to render once with my data
Here is my code:
//my states
const [selectedLeague,setSelectedLeague]=useState({})
const [loading,setLoading]= useState(false)
const [competitions,setCompetitions]= useState([])
const [matchday,setMatchDay]=useState([])
const [matches,setMatches]=useState([])
const [LeagueName,setSelectedLeagueName]=useState([])
const area_ids= [2072,2114,2163,2077,2081,2088,2187,2224]
so then I'm trying to get matches and filter by matchday
const getMatches= async()=>{
const response = await axios.get(`${FOOTBALL_API_URL}/${selectedLeague}/matches`,{
method: 'get',
headers: { 'X-Auth-Token': `${FOOTBALL_API_TOKEN}`}
} );
console.log('checking getmatch response',response)
const data = await response.data
console.log('checking response.data',data)
setLoading(true)
// set matchday
setMatchDay(data.matches[0].season.currentMatchday)
// filter matches by matchday
const filter = data.matches.filter((match)=>{
return matchday === match.matchday
})
// log the filtered array
console.log('filtered array',filter)
setMatches(filter)
}
but I only get the matchday and When filtered list is first rendered it is always an empty list
filtered array []length: 0[[Prototype]]: Array(0)
console log showing empty array on the first render
I've tried tweaking my use effect but it only loops infinitely
React.useEffect(() => {
getMatches()
}, [matches])
but when I leave the page and come back it then gets the data I need
filtered array
(10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {area: {…}, competition: {…}, season: {…}, id: 416384, utcDate: '2022-08-05T19:00:00Z', …}
1: {area: {…}, competition: {…}, season: {…}, id: 416383, utcDate: '2022-08-06T11:30:00Z', …}
2: {area: {…}, competition: {…}, season: {…}, id: 416378, utcDate: '2022-08-06T14:00:00Z', …}
3: {area: {…}, competition: {…}, season: {…}, id: 416379, utcDate: '2022-08-06T14:00:00Z', …}
4: {area: {…}, competition: {…}, season: {…}, id: 416381, utcDate: '2022-08-06T14:00:00Z', …}
5: {area: {…}, competition: {…}, season: {…}, id: 416382, utcDate: '2022-08-06T14:00:00Z', …}
6: {area: {…}, competition: {…}, season: {…}, id: 416377, utcDate: '2022-08-06T16:30:00Z', …}
7: {area: {…}, competition: {…}, season: {…}, id: 416376, utcDate: '2022-08-07T13:00:00Z', …}
8: {area: {…}, competition: {…}, season: {…}, id: 416380, utcDate: '2022-08-07T13:00:00Z', …}
9: {area: {…}, competition: {…}, season: {…}, id: 416375, utcDate: '2022-08-07T15:30:00Z', …}
length: 10
[[Prototype]]: Array(0)
console log showing filtered array with requested data
I need to get my data on the first render, I am new to hooks, so I'm hoping I'm missing something simple. Thanks. please if you have any questions please reply to this trend.
CodePudding user response:
From react official documentation.
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to re-run.
So, please change your useEffect to next
useEffect(() => {
getMatches();
}, []);
And this should solve your problem.
Hope this helps.
CodePudding user response:
//state
....
///
useEffect(()=>{
getMatches().then(resp => setMatches(resp)); //u need to set the state to trigger are-render
}, []); // pass in an empty array to say there are no dependencies that effect should watch
return( matches.length > 0 ? <Component/> : {"Fetching the matches"}); //on the first render, matches will be empty,
The second parameter in useEffect determines when and how often that effect runs, it runs when ever the data place there changes, Usually you want your app to fetch the data once then render, then you should pass in an empty array. In addition, your component will likely mount before the request is completed, so u need to handle what it should render while its waiting. React has a concept called Suspense for this case, or you can simply do a return ( data ? <component/> : "..loading")