Reactjs 使用Typescript将项目批量加载到React上下文状态

Reactjs 使用Typescript将项目批量加载到React上下文状态,reactjs,typescript,Reactjs,Typescript,我有一个React上下文正在工作,但我想将项目批量加载到状态中 上下文有一个减缩器,用于将单个对象添加到上下文存储的对象数组中。在代码(附件)中,问题区域位于提供者初始化的底部。在useEffect中,它执行api获取调用。数据返回,当前使用减速机一次加载一个元素。这是低效的,因为它会导致对侦听上下文的组件的多个呈现调用 我对React和Typescript比较陌生,很难找到正确的编码和语法来阻止Typescript的抱怨 我想将reducer更改为接受一个“load”操作,该操作的有效负载是替

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

上下文有一个减缩器,用于将单个对象添加到上下文存储的对象数组中。在代码(附件)中,问题区域位于提供者初始化的底部。在useEffect中,它执行api获取调用。数据返回,当前使用减速机一次加载一个元素。这是低效的,因为它会导致对侦听上下文的组件的多个呈现调用

我对React和Typescript比较陌生,很难找到正确的编码和语法来阻止Typescript的抱怨

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

我已尝试将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;
import*as React from“React”;
/**自定义类型*/
从“./自定义类型”导入{ActionType};
从“./自定义类型”导入{NewsItemType};
从“./utils/Helpers”导入{apirest};
const MAX_ITEMS=30;
界面状态{
新闻列表:数组;
}
界面位移{
类型:ActionType;
有效载荷:NewsItemType;
}
接口InewContextInterface{
声明:{
新闻列表:数组;
};
updateNewsList:React.Dispatch;
}
const initialState:IState={newsList:[]};
const reducer:React.reducer=(状态、操作)=>{
开关(动作类型){
案例ActionType.add:
返回{
新闻列表:[
行动.有效载荷,
…state.newsList.filter(
newsitem=>newsitem.\u id!==action.payload.\u id
)
]
};
案例ActionType.load:
返回{
新闻列表:[…state.newsList,action.payload]
};
案例ActionType.update:
返回{
新闻列表:state.newsList.map(项=>{
返回项目。_id==action.payload。_id?action.payload:项目;
})
};
案例ActionType.delete:
返回{
新闻列表:state.newsList.filter(
newsitem=>newsitem.\u id!==action.payload.\u id
)
};
违约:
抛出新错误();
}
};
export const newscoxt=React.createContext({
声明:{
新闻列表:[]
},
UpdateNewList:()=>{}
});
const{Provider}=新闻上下文;
const NewsProvider:React.FC=({
儿童
}) => {
const[newsList,updateNewsList]=React.useReducer(reducer,initialState);
React.useffect(()=>{
apiRequest(“http://localhost:5000/news/?limit=“+MAX_项目,“获取”,为真)
.然后(新闻=>{
国际单项体育联合会(新闻){
Array.from(news.forEach)((article:any)=>
updateNewsList({type:ActionType.load,负载:article})
);
}
})
.catch(警报=>{
控制台。错误(警报);
});
}, []);
返回(
{儿童}
);
};
导出默认新闻提供者;

首先,您不会多次调用API请求,因为您将空的依赖项数组设置为
useffect
的第二个参数。因此,在安装组件之后,它只会被调用一次

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

如果希望看到使用React钩子进行数据获取的示例,可以查看中使用的获取程序模式

如果希望reducer同时接受单个元素或数组,则可以这样编写
load
部分:

case ActionType.load:
返回{
新闻列表:[…state.newsList,…Array().concat(action.payload)]
};

您能发布您看到的错误吗?将负载更改为:interface IAction{type:ActionType;payload:NewsItemType | Array;}之后,我在reducer声明中得到了以:type'(state:IState,action:IAction)=>{newsList:(NewsItemType | NewsItemType[])[]]开头的类型脚本错误'不可分配给类型'Reducer'。调用签名返回类型“{newsList:(NewsItemType | NewsItemType[])[];}”和“IState”不兼容。多个调用不是来自多个useEffect调用,请查看内部。然后对于apiRequest,您将看到它具有数组的forEach,在forEach调用中,它将调用reducer以添加一个元素。我想去掉forEach,并进行一次调用来添加数组中的所有元素。我曾尝试通过加载将所有元素添加到数组中,但随后出现typescript语法错误,因为它不喜欢负载可以是数组或单个元素这一事实。