【问题标题】:Bulk loading items into React Context state with Typescript使用 Typescript 将项目批量加载到 React Context 状态
【发布时间】:2020-02-28 14:04:34
【问题描述】:

我有一个正在工作的 React 上下文,但我想将项目批量加载到状态中。

上下文有一个reducer,用于将单个对象添加到上下文存储的对象数组中。在代码(附加)中,问题区域位于提供程序初始化的底部。在 useEffect 中,这会执行 api fetch 调用。数据返回并且当前使用 reducer 一次加载一个元素。这是低效的,因为它会导致对侦听上下文的组件进行多次渲染调用。

我对 React 和 Typescript 比较陌生,并且难以获得正确的编码和语法来阻止 Typescript 抱怨。

我想更改减速器以接受“加载”操作,其中包含替换状态数组中所有当前元素的项目数组的有效负载。我有一个特殊的加载操作,并且一直在尝试将该操作的有效负载作为一个数组,而不更改接受单个项目的其他操作。或者提供一个新函数,将一组对象加载到状态中。

我尝试将 IAction 中的有效负载定义为有效负载:NewsItemType|Array, item NewsItemType }

无论我尝试什么,我都会在 reducer 中遇到语法错误:React.Reducer - 主要是关于返回类型。

任何人都可以提供有关最佳方法的建议吗?

    import * as React from "react";

/** Custom types */
import { ActionType } from "../custom-types";
import { NewsItemType } from "../custom-types";
import { apiRequest } from "../utils/Helpers";

const MAX_ITEMS = 30;

interface IState {
    newsList: Array<NewsItemType>;
}

interface IAction {
    type: ActionType;
    payload: NewsItemType;
}

interface InewsContextInterface {
    state: {
        newsList: Array<NewsItemType>;
    };
    updateNewsList: React.Dispatch<IAction>;
}

const initialState: IState = { newsList: [] };

const reducer: React.Reducer<IState, IAction> = (state, action) => {
    switch (action.type) {
        case ActionType.add:
            return {
                newsList: [
                    action.payload,
                    ...state.newsList.filter(
                        newsitem => newsitem._id !== action.payload._id
                    )
                ]
            };
        case ActionType.load:
            return {
                newsList: [...state.newsList, action.payload]
            };
        case ActionType.update:
            return {
                newsList: state.newsList.map(item => {
                    return item._id === action.payload._id ? action.payload : item;
                })
            };
        case ActionType.delete:
            return {
                newsList: state.newsList.filter(
                    newsitem => newsitem._id !== action.payload._id
                )
            };
        default:
            throw new Error();
    }
};

export const newsContext = React.createContext<InewsContextInterface>({
    state: {
        newsList: []
    },
    updateNewsList: () => { }
});

const { Provider } = newsContext;

const NewsProvider: React.FC<{ children: React.ReactNode }> = ({
    children
}) => {
    const [newsList, updateNewsList] = React.useReducer(reducer, initialState);

    React.useEffect(() => {
        apiRequest("http://localhost:5000/news/?limit=" + MAX_ITEMS, "get", true)
            .then(news => {
                if (news) {
                    Array.from(news).forEach((article: any) =>
                        updateNewsList({ type: ActionType.load, payload: article })
                    );
                }
            })
            .catch(alert => {
                console.error(alert);
            });
    }, []);

    return (
        <Provider value={{ state: newsList, updateNewsList }}>{children}</Provider>
    );
};

export default NewsProvider;

【问题讨论】:

  • 你能发布你看到的错误吗?
  • 将payload更改为:interface IAction { type: ActionType;有效载荷:NewsItemType |数组;我在减速器声明中收到打字稿错误,其开头为: Type '(state: IState, action: IAction) => { newsList: (NewsItemType | NewsItemType[])[]; }' 不可分配给类型 'Reducer'。调用签名返回类型 '{ newsList: (NewsItemType | NewsItemType[])[]; }' 和 'IState' 不兼容。

标签: reactjs typescript


【解决方案1】:

首先,您不会多次调用 API 请求,因为您设置了一个空的依赖数组作为useEffect 的第二个参数。所以它只会在组件被挂载后被调用一次。

关于减速器中的错误,如果不准确知道错误消息,将很难回答。

如果您想查看使用 React 钩子获取数据的示例,可以查看 this file 中使用的 fetcher 模式。

如果你想让你的 reducer 同时接受单个元素或数组,你可以像这样编写load 部分:

case ActionType.load:
  return {
    newsList: [...state.newsList, ...Array<NewsItemType>().concat(action.payload)]
  };

【讨论】:

  • 多个调用不是来自多个 useEffect 调用,查看 .then 内部的 apiRequest 你会看到它有一个 forEach 用于 Array,在 forEach 调用中它会调用 reducer 添加一个元素。我想摆脱 forEach 并有一个调用来添加数组中的所有元素。我尝试通过加载添加数组中的所有元素,但随后出现打字稿语法错误,因为它不喜欢有效负载可以是数组或单个元素的事实。
猜你喜欢
  • 2021-06-28
  • 1970-01-01
  • 2019-09-03
  • 2021-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
相关资源
最近更新 更多