본문 바로가기
개발(라이브러리,프레임워크)/react.js & react native

Async Action

by zieunee 2022. 1. 31.
반응형

비동기작업 어디서 하느냐가 제일 중요하다.

  1. 액션을 분리
  2. dispatch를 할때 비동기 작업 해준다.
    1. 리듀서는 동기적인것
    2. dispatch도 동기적인것

App.js

import './App.css';
import TodoListContainer from './containers/TodoListContainer'
import TodoFormContainer from './containers/TodoFormContainer'
import UserListContainer from './containers/UserListContainer';

function App() {
  return (
    <div className="App">
      <header className="App-header">
          <UserListContainer/>
          <TodoListContainer />
          <TodoFormContainer />
      </header>
    </div>
  );
}

export default App;

reducer.js

import { combineReducers } from 'redux'
import todos  from './todos'
import filter  from './filter'
import users  from './users'
const reducer = combineReducers({
    todos,
    filter,
    users
})

export default reducer;

actions.js

export const ADD_TODO = "ADD_TODO"
export const COMPLETE_TODO = 'COMPLETE_TODO';

// {type : ADD_TODO , text: '할일'}
export function addTodo(text) {
    return {
        type: ADD_TODO,
        text,
    };
}
// {type : COMPLETE_TODO , text: 3} > 완성된 index 값
export function completeTodo(index) {
    return {
        type: COMPLETE_TODO,
        index,
    };
}
export const SHOW_ALL = 'SHOW_ALL';
export const SHOW_COMPLETE = 'SHOW_COMPLETE';

export function showAll() {
    return {type:SHOW_ALL};
}
export function showComplete() {
    return {type: SHOW_COMPLETE};
}

//users
//깃헙 api 호출 시작
export const GET_USERS_START = 'GET_USERS_START';
//깃헙 api 호출이 성공적으로 들어온 경우
export const GET_USERS_SUCCESS = 'GET_USERS_SUCCESS';
//깃헙 api 호출이 실패한 경우
export const GET_USERS_FAIL = 'GET_USERS_FAIL';

export function getUsersStart() {
    return {
        type: GET_USERS_START
    };
}
export function getUsersSuccess(data) {
    return {
        type: GET_USERS_SUCCESS,
        data,
    };
}
export function getUsersFail(error) {
    return {
        type: GET_USERS_FAIL,
        error,
    };
}

users.js

import { GET_USERS_FAIL, GET_USERS_START, GET_USERS_SUCCESS } from "../actions";

const initialState =  {
    loading: false,
    data: [],
    error: null
};

export default function users(state = initialState, action) {
    if(action.type === GET_USERS_START){
        return {
            ...state,
            loading: true,
            error: null,
        };
    }
    if(action.type === GET_USERS_SUCCESS){
        return {
            ...state,
            loading: false,
            data: action.data,
        };
    }
    if(action.type === GET_USERS_FAIL){
        return {
            ...state,
            loading: false,
            error: action.error,
        };
    }
    return state;
}

UserList.jsx

import { useEffect } from "react"
import axios from "axios";
export default function UserList({users , start, success, fail}) {
    useEffect(() => {
        async function getUsers(){
            try {
                start()
                const res = await axios.get('https://api.github.com/users');
                success(res.data);
            }catch(error){
                fail(error);
            }
        }
        getUsers();
    },[start, success, fail]);

    if(users.length === 0){
        return <p>현재 유저 정보 없음</p>
    }

    return (
        <ul>
            {users.map((user) => (
                <li key={user.id}>{user.login}</li>
            ))}
        </ul>
    );
}

UserListContainer.jsx

import { useCallback } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux"
import UserList from "../components/UserList"
import { getUsersFail, getUsersStart, getUsersSuccess } from "../redux/actions";

export default function UserListContainer(){
    const users = useSelector((state) => state.users.data);
    const dispatch = useDispatch();

    const start = useCallback(() => {
        dispatch(getUsersStart()); 
    }, [dispatch]);

    const success = useCallback((data) => {
        dispatch(getUsersSuccess(data)); 
    }, [dispatch]);

    const fail = useCallback((error) => {
        dispatch(getUsersFail(error)); 
    }, [dispatch]);

    return <UserList users={users} start={start} success={success} fail={fail} />
}

더 쉽게 만들기

객체 모아서 하나로 전달하기

비동기 로직을 container로 넣어주고

userList는 데이터를 받아서 보여주는 역할만 한다.

userList.jsx

import { useEffect } from "react"

export default function UserList({users , getUsers}) {
    useEffect(() => {
        getUsers();
    },[getUsers]);

    if(users.length === 0){
        return <p>현재 유저 정보 없음</p>
    }

    return (
        <ul>
            {users.map((user) => (
                <li key={user.id}>{user.login}</li>
            ))}
        </ul>
    );
}

userListContainer.jsx

import { useCallback } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux"
import UserList from "../components/UserList"
import { getUsersFail, getUsersStart, getUsersSuccess } from "../redux/actions";
import axios from "axios";

export default function UserListContainer(){
    const users = useSelector((state) => state.users.data);
    const dispatch = useDispatch();

    const getUsers = useCallback(async() => {
            try {
                dispatch(getUsersStart()); 
                const res = await axios.get('https://api.github.com/users');
                dispatch(getUsersSuccess(res.data)); ;
            }catch(error){
                dispatch(getUsersFail(error)); 
            }
    },[dispatch]);

    return <UserList users={users} getUsers={getUsers} />
}
반응형

'개발(라이브러리,프레임워크) > react.js & react native' 카테고리의 다른 글

redux-devtools  (0) 2022.02.02
리덕스 미들웨어  (0) 2022.02.01
Redux 를 React에 연결(라이브러리x)  (0) 2022.01.21
Redux 개요, 사용  (0) 2022.01.20
Hooks  (0) 2022.01.09