Как использовать топор ios, чтобы получить элементы API в редуксе? - PullRequest
3 голосов
/ 15 января 2020

Я изучаю Redux, так что это может быть базовый c вопрос и ответ, но здесь мы go.

Я пытаюсь получить список элементов из моего бэкэнда API (/api/items) и передать их в мой ShoppingList.js компонент, чтобы при загрузке компонента отображался список элементов. Я думаю, что мне нужно получить данные в действии, а затем вызвать это действие в хуке useEffect в компоненте реакции, но я не слишком уверен, так как не могу заставить его работать.

Может кто-нибудь помочь мне разобраться?

Redux. js

import { createStore } from 'redux';
import axios from 'axios';

const initialState = {
    items: [],
    loading: false,
};

export const store = createStore(
    reducer,
    initialState,
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

function reducer(state, action) {
    switch (action.type) {
        case 'GET_ITEMS':
            return {
                ...state,
                items: action.payload,
                loading: false,
            };
        case 'ADD_ITEM':
            return {
                ...state,
                items: [...state.items, action.payload],
            };
        case 'DELETE_ITEM':
            return {
                ...state,
                items: state.items.filter(item => item.id !== action.payload),
            };
        case 'ITEMS_LOADING':
            return {
                ...this.state,
                loading: true,
            };
        default:
            return state;
    }
}

export const getItemsAction = () => ({
    return(dispatch) {
    console.log('here');
    axios.get('api/items').then(response => {
        console.log(response);
        dispatch({ type: 'GET_ITEMS', payload: response.data });
    });
},
});

export const addItemAction = item => ({
    type: 'ADD_ITEM',
    payload: item,
});

export const deleteItemAction = item => ({
    type: 'DELETE_ITEM',
    payload: item,
});

export const setItemsLoading = () => ({
    type: 'ITEMS_LOADING',
});

ShoppingList. js

export default function ShoppingList() {
    const items = useSelector(state => state.items);

    const dispatch = useDispatch();
    const addItem = name => dispatch(addItemAction(name));
    const deleteItem = id => dispatch(deleteItemAction(id));

    useEffect(() => {
        //call get items dispatch?
        getItemsAction();
    });

    return (
        <div className="container mx-auto">
            <button
                onClick={() => {
                    const name = prompt('Enter Item');
                    if (name) {
                        // setItems([...items, { id: uuid(), name: name }]);
                        addItem({
                            id: uuid(),
                            name: name,
                        });
                    }
                }}
                className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-4"
            >
                Add Item
            </button>

            <ul className="mt-4">
                <TransitionGroup className="shopping-list">
                    {items.map(({ id, name }) => (
                        <CSSTransition
                            key={id}
                            timeout={500}
                            classNames="fade"
                            style={{ marginBottom: '0.5rem' }}
                        >
                            <li>
                                {' '}
                                <button
                                    className="bg-red-500 rounded px-2 mr-2 text-white"
                                    onClick={deleteItem.bind(this, id)}
                                >
                                    &times;
                                </button>
                                {name}
                            </li>
                        </CSSTransition>
                    ))}
                </TransitionGroup>
            </ul>
        </div>
    );
}

1 Ответ

2 голосов
/ 15 января 2020

Вы находитесь рядом с тем местом, где вам нужно, пропавшая часть заключается в том, что избыточность синхронна, поэтому вам нужно использовать что-то вроде redux-thunk или redux-saga для обработки асинхронных c действий, таких как сетевые запросы.

Как только вы настроите любую нужную вам библиотеку, вы будете вызывать ее аналогично вызову действия с избыточностью, начиная с useEffect, как вы предлагаете.

Например, если вы используете thunk :

export const getItemsAction = () => ({
    return (dispatch) => {
        axios.get('api/items').then(response => {
            console.log(response)
            dispatch({ type: 'GET_ITEMS_SUCCESS', payload: response.data })
        }).catch(err => dispatch({ type: 'GET_ITEMS_ERROR', error: err })
    },
})

Тогда вы можете вызвать его из вашего effect:

    useEffect(() => {
        dispatch(getItemsAction())
    }, []);

Убедитесь, что вы добавили пустой массив зависимостей, если хотите вызывать его только один раз, иначе он будет Вам звонят каждый раз, когда ваш компонент обновляется.

Обратите внимание, что thunk может отправлять другие редукционные действия, и я изменил несколько типов ваших действий, чтобы было более понятно, что происходит; GET_ITEMS_SUCCESS устанавливает ваш успешный ответ, а GET_ITEMS_ERROR устанавливает любую ошибку, если она есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...