redux中如何使用axios获取api项?

Posted

技术标签:

【中文标题】redux中如何使用axios获取api项?【英文标题】:How to use axios to get api items in redux? 【发布时间】:2020-05-02 11:47:39 【问题描述】:

我正在学习 Redux,所以这可能是一个基本的问题和答案,但我们开始吧。

我正在尝试从我的后端 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',
);

购物清单.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】:

您已经接近您需要的位置,缺少的部分是 redux 是同步的,因此您需要使用 redux-thunkredux-saga 之类的东西来处理网络请求等异步操作。

一旦你设置了任何你想要的库,你可以像调用一个 redux 操作一样调用它,从 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 能够调度其他 redux 操作,我更改了您的一些操作类型以更清楚地了解发生了什么; GET_ITEMS_SUCCESS 设置您的成功响应,GET_ITEMS_ERROR 设置任何错误(如果有)。

【讨论】:

那会是这样吗? export const getItemsAction = () =&gt; ( return(dispatch) axios.get('api/items').then(response =&gt; console.log(response); dispatch( type: 'GET_ITEMS', payload: response.data ); ); , ); 是的,我编辑了我的答案以帮助解释我将如何使用 thunk 来做到这一点 好的,谢谢,我已经按照您的建议进行了更改,但现在我在 useEffect 挂钩中收到 Actions may not have an undefined "type" property. 错误。知道为什么会这样吗?类型设置为“GET_ITEMS”,在我的减速器中为“GET_ITEMS”。 您需要确保 thunk 调度的任何操作类型都在您的减速器中,因此请确保 GET_ITEMS_SUCCESS 和 GET_ITEMS_ERROR 在您的减速器中。 GET_ITEMS 本身是不需要的 对,GET_ITEMS_SUCCESS 和 GET_ITEMS_ERROR 在我的减速器中,但我仍然在 dispatch(getItemsAction()); 处收到相同的错误消息

以上是关于redux中如何使用axios获取api项?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 redux 和 redux-promise 将多个 axios 调用合并到一个有效负载中?

使用 Axios 在 Redux 中处理 api 调用

如何在 redux 中使用 axios 库将数据发布到 API 服务器

当api通过reducer来自状态时如何使用axios获取?

无法使用 ReactJs、Axios、Redux 渲染/显示从 api 获取的数据

如何使用 redux 中的 axios 库为发布到 API 服务器的数据自动生成唯一 ID