EinfĂŒhrung
Eine beliebte Bibliothek fĂŒr die Arbeit mit dem Status von Webanwendungen in React-Js ist Redux. Es hat jedoch eine Reihe von Nachteilen wie die AusfĂŒhrlichkeit (auch in Verbindung mit dem Redux-Toolkit) und die Notwendigkeit, eine zusĂ€tzliche Ebene auszuwĂ€hlen (Redux-Thunk, Redux-Saga, Redux-Observable). Es besteht das GefĂŒhl, dass dies irgendwie allzu kompliziert ist und es lange Zeit Hooks gab, insbesondere den useContext-Hook. Also habe ich eine andere Lösung ausprobiert.
Anwendung testen
« » create react app, typescript, redux-toolkit, redux saga. redux context + react-query. , , , react-query . .. , .. , . .. .
react-query , , .. redux 2 . â , . â , .
react-context. :
export const CitiesProvider = ({
children,
}: {
children: React.ReactNode;
}): JSX.Element => {
const [citiesState, setCitiesState] = useLocalStorage<CitiesState>(
'citiesState',
citiesStateInitValue,
);
const addCity = (id: number) => {
if (citiesState.citiesList.includes(id)) {
return;
}
setCitiesState(
(state: CitiesState): CitiesState => ({
...state,
citiesList: [...citiesState.citiesList, id],
}),
);
};
// removeCity.., setCurrentCity..
return (
<itiesContext.Provider
value={{
currentCity: citiesState.currentCity,
cities: citiesState.citiesList,
addCity,
removeCity,
setCurrentCity,
}}
>
{children}
</itiesContext.Provider>
);
};
, setCurrentCity, removeCity
. , localStorage . , , , , .
React-query
, , react-query. :
import { QueryClient, QueryClientProvider } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { CitiesProvider } from './store/cities/cities-provider';
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<CitiesProvider>
<App />
:
const queryCities = useQuery('cities', fetchCitiesFunc);
const cities = queryCities.data || [];
'cities'
, . - , Promise, . .
useQuery UseQueryResult
, ,
const { isLoading, isIdle, isError, data, error } = useQuery(..
export function useCurrentWeather(): WeatherCache {
const { currentCity } = useContext(itiesContext);
//
const queryCities = useQuery('cities', fetchCitiesFunc, {
refetchOnWindowFocus: false,
staleTime: 1000 * 60 * 1000,
});
const citiesRu = queryCities.data || [];
// ..
const city = citiesRu.find((city) => {
if (city === undefined) return false;
const { id: elId } = city;
if (currentCity === elId) return true;
return false;
});
const { id: weatherId } = city ?? {};
//
const queryWeatherCity = useQuery(
['weatherCity', weatherId],
() => fetchWeatherCityApi(weatherId as number),
{
enabled: !!weatherId,
staleTime: 5 * 60 * 1000,
},
);
const { coord } = queryWeatherCity.data ?? {};
// .
const queryForecastCity = useQuery(
['forecastCity', coord],
() => fetchForecastCityApi(coord as Coord),
{
enabled: !!coord,
staleTime: 5 * 60 * 1000,
},
);
return {
city,
queryWeatherCity,
queryForecastCity,
};
}
staleTime
â , , . , . , staleTime =0
.
enabled: !!weatherId
, . useQuery
isIdle
. .
const queryWeatherCity = useQuery(['weatherCity', weatherId],..
, , + .
:
export function Forecast(): React.ReactElement {
const {
queryForecastCity: { isFetching, isLoading, isIdle, data: forecast },
} = useCurrentWeather();
if (isIdle) return <LoadingInfo text=" " />;
if (isLoading) return <LoadingInfo text=" " />;
const { daily = [], alerts = [], hourly = [] } = forecast ?? {};
const dailyForecastNext = daily.slice(1) || [];
return (
<>
<Alerts alerts={alerts} />
<HourlyForecast hourlyForecast={hourly} />
<DailyForecast dailyForecast={dailyForecastNext} />
{isFetching && <LoadingInfo text=" " />}
</>
);
}
isLoading â isFetching - .
React-query . Redux, ( )
, Actions, , , .. , , , . . :
import { ReactQueryDevtools } from 'react-query/devtools';
, process.env.NODE_ENV === 'production'
, . Create React App .
react-query , , , .
useQueries
. ..useQuery
.
const userQueries = useQueries(
users.map(user => {
return {
queryKey: ['user', user.id],
queryFn: () => fetchUserById(user.id),
}
})
, , 3 .
retry
.
, ,
useMutations
const mutation = useMutation(newTodo => axios.post('/todos', newTodo))
,
useInfiniteQuery
, , , .
Nach dem Ersetzen von Redux-Toolkit + Redux-Saga und Kontext + React-Query schien mir der Code viel einfacher zu sein, und ich hatte sofort mehr Funktionen fĂŒr die Arbeit mit Anfragen an den Server. Der React-Context-Teil verfĂŒgt jedoch nicht ĂŒber spezielle Debugging-Tools und wirft im Allgemeinen Bedenken auf. Er erwies sich jedoch als recht klein und React-Devtools waren genug fĂŒr mich. Im Allgemeinen bin ich mit der React-Query-Bibliothek zufrieden, und im Allgemeinen erscheint mir die Idee, den Cache in eine separate EntitĂ€t zu unterteilen, interessant. Trotzdem ist dies eine sehr kleine Anwendung mit mehreren Get-Anfragen.
Links
Das Layout ist nur fĂŒr mobile GerĂ€te korrekt