'Why is the reducer set back to initial state after fetch error? React
I'm learning react with the github API. I have a github reducer where is all the data saved. After the search, the api gives me back an array with the names, and when I visit one specific user, then I get his repos and stuff like that. So when I click on on the user, the url will be like this: "/user/someone". When I type some gibberish like "/user/sdfasdfsadfsadf" so the person doesn't exists, then It goes to 404 page, which is ok, but all the data is lost, the array of "users" and also the "user" data.
Here is the github context API:
import { createContext, useState, useContext, useReducer } from 'react';
import githubReducer from '../github/GithubReducer';
const GithubContext = createContext();
const GITHUB_URL = process.env.REACT_APP_GITHUB_URL;
const GITHUB_TOKEN = process.env.REACT_APP_GITHUB_TOKEN;
const GithubProvider = (props) => {
const initialState = {
search: '',
users: [],
user: {},
repos: null,
loading: false,
};
const [state, dispatch] = useReducer(githubReducer, initialState);
// get search results
const searchUsers = async (text) => {
try {
setLoading();
const params = new URLSearchParams({
q: text,
});
const response = await fetch(`${GITHUB_URL}/search/users?${params}`, {
header: {
Authorization: `token ${GITHUB_TOKEN}`,
},
});
if (!response.ok) throw new Error('Too much fetch');
const { items } = await response.json();
dispatch({ type: 'getUsers', payload: { items, text } });
} catch (e) {
console.log(e);
}
};
// get user
const getUser = async (login) => {
try {
setLoading();
const response = await fetch(`${GITHUB_URL}/users/${login}`, {
header: {
Authorization: `token ${GITHUB_TOKEN}`,
},
});
if (!response.ok) throw new Error(response);
const data = await response.json();
dispatch({ type: 'getUser', payload: data });
} catch (e) {
console.log(e);
window.location = `${process.env.PUBLIC_URL}/notfound`;
}
};
const getRepos = async (login) => {
try {
const response = await fetch(`${GITHUB_URL}/users/${login}/repos?per_page=10&sort=created`, {
header: {
Authorization: `token ${GITHUB_TOKEN}`,
},
});
if (!response.ok) throw new Error('response error');
const data = await response.json();
dispatch({ type: 'getRepos', payload: data });
} catch (e) {
console.log(e);
window.location = `${process.env.PUBLIC_URL}/notfound`;
}
};
//set loading
const setLoading = () => dispatch({ type: 'setLoading' });
//delete users
const deleteUsers = () => dispatch({ type: 'deleteUsers' });
return (
<GithubContext.Provider
value={{
users: state.users,
search: state.search,
loading: state.loading,
searchUsers,
fetchError,
deleteUsers,
user: state.user,
getUser,
getRepos,
repos: state.repos,
}}
{...props}
/>
);
};
const useGithub = () => {
const context = useContext(GithubContext);
if (!context) throw new Error('Not inside of provider');
return context;
};
export { GithubProvider, useGithub };
I know maybe the window.location also refresh the page, and that's also cause the problem, but without that code line the github reducer will be set to his initial state.
Github reducer:
const githubReducer = (state, action) => {
switch (action.type) {
case 'getUsers': {
return { ...state, users: action.payload.items, search: action.payload.text, loading: false };
}
case 'getUser': {
return { ...state, user: action.payload, loading: false };
}
case 'getRepos':
return { ...state, repos: action.payload };
case 'setLoading': {
return { ...state, loading: true };
}
case 'deleteUsers': {
return { ...state, users: [] };
}
default:
return state;
}
};
So when the getUser function fails, the users property shouldn't be changed, the catch function just log the error (as I said above without the window.location code line, )the result is the same, the users array will be empty)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
