반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- TensorFlow
- Android
- react
- node
- MAC
- localserver
- xcode
- build
- vsCode
- webpack
- 티스토리챌린지
- 오블완
- unittest
- 센토스
- centos
- 맥
- IOS
- androidstudio
- Chrome
- MachineLearning
- 개발
- 리눅스
- jest
- linux
- VirtualBox
- PYTHON
- ReactNative
- qunit
- 네트워크
Archives
- Today
- Total
로메오의 블로그
[React Native] Redux toolkit & Network call 본문
반응형
https://randomuser.me/documentation#pagination
Api 더미 데이터는 위 사이트에서 가져옵니다.
App.tsx
import React from 'react';
import {SafeAreaView, StatusBar} from 'react-native';
import {Provider as ReduxProvider} from 'react-redux';
import UserList from './UserList';
import store from './store';
const App = () => {
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ReduxProvider store={store}>
<UserList />
</ReduxProvider>
</SafeAreaView>
</>
);
};
export default App;
store.ts
import {combineReducers, configureStore} from '@reduxjs/toolkit';
import userListSlice from './userListSlice';
const rootReducer = combineReducers({
userList: userListSlice,
});
export type RootState = ReturnType<typeof rootReducer>;
const store = configureStore({
reducer: rootReducer,
});
export default store;
apiClient.ts
import {User} from './userListSlice';
type ResponseKind = 'success' | 'failure';
type NetworkResponse<T> = {
kind: ResponseKind;
body?: T;
};
export const fetchUsers = async (
page: number,
count: number,
): Promise<NetworkResponse<User[]>> => {
const response = await fetch(
`https://randomuser.me/api/?page=${page}&results=${count}`,
{
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
if (response.ok) {
const json = await response.json();
return {
kind: 'success',
body: json.results,
};
} else {
return {
kind: 'failure',
};
}
};
userListSlice.ts
import {createAsyncThunk, createSlice} from '@reduxjs/toolkit';
import * as apiClient from './apiClient';
export type User = {
name: {
first: string;
};
picture: {
thumbnail: string;
};
};
export type UserListState = {
users: User[];
loading: boolean;
error?: boolean;
nextPage: number;
};
const initialState: UserListState = {
users: [],
loading: false,
error: true,
nextPage: 1,
};
/**
* Redux Toolkit 비동기 처리
*/
export const fetchUsers = createAsyncThunk<{users: User[]}, {page: number}>(
'fetchUsers',
async ({page}) => {
const response = await apiClient.fetchUsers(page, 10);
if (response.kind === 'success') {
return {
users: response.body ?? [],
};
} else {
throw 'Error fetching users';
}
},
);
/**
* thunk slice
*/
const userListSlice = createSlice({
name: 'userList',
initialState: initialState,
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchUsers.pending, state => {
state.loading = true;
state.error = undefined;
})
.addCase(fetchUsers.fulfilled, (state, action) => {
state.nextPage += 1;
state.users = state.users.concat(action.payload.users);
state.loading = false;
})
.addCase(fetchUsers.rejected, state => {
state.error = true;
state.loading = false;
});
},
});
export default userListSlice.reducer;
Redux Toolkit 비동기 처리는 아래 사이트에서 확인하세요.
https://redux-toolkit.js.org/api/createAsyncThunk
https://velog.io/@raejoonee/createAsyncThunk
UserList.tsx
import React, {FunctionComponent, useEffect} from 'react';
import {FlatList, StyleSheet, Text, View, Image} from 'react-native';
import {useDispatch, useSelector} from 'react-redux';
import {RootState} from './store';
import {fetchUsers, User} from './userListSlice';
const UserList: FunctionComponent = () => {
const dispatch = useDispatch();
const screenState = useSelector((state: RootState) => state.userList);
useEffect(() => {
dispatch(fetchUsers({page: 1}));
}, []);
const handleOnEndReached = () => {
if (!screenState.loading) {
dispatch(fetchUsers({page: screenState.nextPage}));
}
};
return (
<>
{screenState.loading && <Text>LOADING</Text>}
{screenState.error && <Text>ERROR</Text>}
{!screenState.loading && !screenState.error && <Text>DEFAULT</Text>}
<FlatList
data={screenState.users}
keyExtractor={(_, index) => {
return index.toString();
}}
renderItem={({item}) => <UserListItem user={item} />}
onEndReached={handleOnEndReached}
/>
</>
);
};
const UserListItem: FunctionComponent<{user: User}> = ({user}) => {
return (
<View style={style.container}>
<Image style={style.thumbnail} source={{uri: user.picture.thumbnail}} />
<Text style={style.nameText}>{user.name.first}</Text>
</View>
);
};
const style = StyleSheet.create({
container: {
flexDirection: 'row',
padding: 15,
alignItems: 'center',
},
nameText: {
padding: 15,
},
thumbnail: {
width: 50,
height: 50,
borderRadius: 25,
borderColor: 'purple',
borderWidth: 3,
},
});
export default UserList;
반응형
'Frontend > React' 카테고리의 다른 글
[React Native] 디버그 [Chrome DevTools & Safari] (0) | 2022.11.15 |
---|---|
[React Native] Redux toolkit & Todo App (2) | 2022.11.12 |
[React Native] Redux toolkit (0) | 2022.11.08 |
[React Native] Draggable FlatList (0) | 2022.10.24 |
[React Native] props (0) | 2022.10.20 |
Comments