pengantar
Perpustakaan populer untuk bekerja dengan status aplikasi web di react-js adalah redux. Namun, ini memiliki sejumlah kelemahan seperti verbositas (bahkan dalam hubungannya dengan redux-toolkit), kebutuhan untuk memilih lapisan tambahan (redux-thunk, redux-saga, redux-observable). Ada perasaan bahwa entah bagaimana ini terlalu rumit dan untuk waktu yang lama ada pengait dan khususnya pengait useContext .. Jadi saya mencoba solusi lain.
Uji aplikasi
ยซ ยป 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
, , , .
Setelah mengganti redux-toolkit + redux-saga dan konteks + react-query, kodenya tampak jauh lebih mudah bagi saya dan saya mendapatkan lebih banyak fungsi di luar kotak untuk menangani permintaan ke server. Namun, bagian react-context tidak memiliki alat debugging khusus dan umumnya menimbulkan kekhawatiran, tetapi ternyata cukup kecil dan react-devtools sudah cukup bagi saya. Secara umum, saya puas dengan pustaka react-query dan, secara umum, gagasan untuk memisahkan cache menjadi entitas terpisah tampaknya menarik bagi saya. Tapi tetap saja ini adalah aplikasi yang sangat kecil dengan beberapa permintaan get ..
Tautan
Tata letak hanya benar untuk perangkat seluler