Reputation: 57
I am trying to make a React project which fetches data from an API, and I'm trying to use useReducer hook with useContext from an external file. Folder Structure:
reducer.js:
const reducer = (currentState, action)=>{
switch(action.type){
case 'setBreedList':
// console.log('setBreedList ran')
return {...currentState, breedList: [...currentState.breedList, action.payload]}
// return currentState
// return {...currentState.breedList, action.payload}
default:
return currentState
}
}
export default reducer
context.js
import React, {useContext, useReducer} from 'react';
import reducer from './reducer';
const AppContext = React.createContext();
const initalState = {
breedList: [],
imageList: []
}
const AppProvider = ({children})=>{
const [state, dispatch] = useReducer(reducer, initalState);
const fetchAllBreeds = ()=>{
fetch('https://dog.ceo/api/breeds/list/all')
.then(res=>res.json())
.then(data=>dispatch({type: 'setBreedList', payload: data}))
}
return (
<AppContext.Provider value={{...state, fetchAllBreeds}}>
{children}
</AppContext.Provider>
)
}
export const useGlobalContext = ()=>{
return useContext(AppContext)
}
export {AppContext, AppProvider}
and this is index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {AppProvider} from './utils/context';
ReactDOM.render(
<React.StrictMode>
<AppProvider>
<App />
</AppProvider>
</React.StrictMode>,
document.getElementById('root')
);
and finally, this is Input.jsx, where I call the fetchAllBreeds
function:
import React from 'react'
import {useGlobalContext} from '../utils/context'
const Input = () => {
const {state, fetchAllBreeds} = useGlobalContext();
fetchAllBreeds();
console.log('hello')
return (
<div>
<p>hello</p>
</div>
)
}
export default Input
Now, when I try to call the fetchAllBreeds
function in the Input.jsx file above, it prints on the console, 'hello', endlessly. I can't figure out why this is happening and I have tried some different things, but the result is the same. Will be grateful to your help.
Upvotes: 0
Views: 329
Reputation: 1763
Input
component is calling fetchAllBreeds
function, that will update the context value which in turn will re-render Input
component, hence fetchAllBreeds
will re-run. Don't call any method inside the component body which will cause re-renders.
Use useEffect
hook inside Input
component. which will execute only once.
import React, {useEffect} from 'react'
import {useGlobalContext} from '../utils/context'
const Input = () => {
const {state, fetchAllBreeds} = useGlobalContext();
useEffect(()=>{
fetchAllBreeds();
}, [])
return (
<div>
<p>hello</p>
</div>
)
}
export default Input
Upvotes: 4