简体   繁体   English

如何将 JSON 对象数组中的项目添加到 Reducer 中的数组?

[英]How to add the items from a array of JSON objects to an array in Reducer?

So I am fetching the list of 10 todos fromhttps://jsonplaceholder.typicode.com/todos?_limit=10&page=1所以我从https://jsonplaceholder.typicode.com/todos?_limit=10&page=1获取 10 个待办事项列表

I am updating data with the array of these 10 todos.我正在用这 10 个待办事项的数组更新数据。 I have a reducer with action type INITIALUPDATE which I want to set the initialState to the list of todos.我有一个动作类型为 INITIALUPDATE 的减速器,我想将 initialState 设置为待办事项列表。 So, now initialState is an empty array [], but after the dispatch it should be the same as data.所以,现在 initialState 是一个空数组 [],但是在 dispatch 之后它应该和 data 一样。

List Notes Screen列出备注屏幕

import { View, Text, FlatList, Button, TouchableOpacity } from "react-native";
import React, { useContext, useState, useEffect } from "react";
import { NotesContext } from "../context/NotesContext";
import { AntDesign } from "@expo/vector-icons";
import { Entypo } from "@expo/vector-icons";
import { Feather } from "@expo/vector-icons";
import axios from "axios";

export default function ListNotes({ navigation }) {
  const [data, setData] = useState(null);
  const [reloadButton, setReloadButton] = useState(false);
  const [user, setUser] = useState(null);
  const [isLoading, setIsLoading] = useState(false);
  const [hasError, setErrorFlag] = useState(false);
  const { state, dispatch } = useContext(NotesContext);
  useEffect(() => {
    const source = axios.CancelToken.source();
    const url = `https://jsonplaceholder.typicode.com/todos?_limit=10&page=1`;
    const fetchUsers = async () => {
      try {
        setIsLoading(true);
        const response = await axios.get(url, { cancelToken: source.token });
        if (response.status === 200) {
          setData(response.data);
          setIsLoading(false);
          console.log(data);
          return;
        } else {
          throw new Error("Failed to fetch users");
        }
      } catch (error) {
        if (axios.isCancel(error)) {
          console.log("Data fetching cancelled");
        } else {
          setErrorFlag(true);
          setIsLoading(false);
        }
      }
    };
    fetchUsers();
    return () => source.cancel("Data fetching cancelled");
  }, [reloadButton]);

  return (
    <View style={{ flex: 1 }}>
      <View style={{ alignItems: "center" }}>
        <TouchableOpacity
          style={{
            marginTop: 5,
            backgroundColor: "blue",
            width: 60,
            height: 60,
            borderRadius: 30,
            alignItems: "center",
            justifyContent: "center",
          }}
          onPress={() => {
            setAddButtonState(addButtonState == true ? false : true);
            dispatch({
              type: "ADD",
              payload: { title: data.title, content: data.body },
            });
          }}
        >
          <AntDesign name="pluscircleo" size={24} color="white" />
        </TouchableOpacity>
      </View>
      <FlatList
        data={state}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => {
          return (
            <TouchableOpacity
              style={{
                marginHorizontal: 10,
                marginBottom: 5,
                backgroundColor: "white",
                borderRadius: 5,
                height: 35,
                elevation: 4,
                flexDirection: "row",
                alignItems: "center",
                justifyContent: "space-between",
              }}
              onPress={() => {
                navigation.navigate("Show", { id: item.id });
              }}
            >
              <View style={{ width: 250 }}>
                <Text style={{ fontSize: 24, marginLeft: 10 }}>
                  {item.title}
                </Text>
              </View>

              <View style={{ flexDirection: "row" }}>
                <TouchableOpacity
                  onPress={() => dispatch({ type: "DELETE", payload: item.id })}
                >
                  <Entypo name="trash" size={30} color="red" />
                </TouchableOpacity>
                <TouchableOpacity
                  onPress={() => navigation.navigate("Update", { id: item.id })}
                >
                  <Feather name="edit" size={30} color="black" />
                </TouchableOpacity>
              </View>
            </TouchableOpacity>
          );
        }}
      />
    </View>
  );
}

NotesContext.js NotesContext.js

import React, { createContext, useReducer } from "react";
import { reducer as NotesReducer, initialState } from "../reducer/Notes";

export const NotesContext = createContext();

export const NotesProvider = ({ children }) => {
  const [state, dispatch] = useReducer(NotesReducer, initialState);
  return (
    <NotesContext.Provider value={{ state: state, dispatch: dispatch }}>
      {children}
    </NotesContext.Provider>
  );
};

Notes Reducer笔记减速机

export const initialState = [];

export const reducer = (state, { type, payload }) => {
  switch (type) {
    case "ADD":
      return [
        ...state,
        {
          id: Math.random(),
          title: payload.title,
          content: payload.content,
        },
      ];
    case "DELETE":
      return state.filter((note) => payload !== note.id);
    case "UPDATE":
      return state.map((record) => {
        if (payload.id == record.id) return payload;
        else return record;
      });
    case "INITIALUPDATE":
      return [
        ...state,
        payload.map((item) => {
          
        })
      ]
  }
  return state;
};

Looking at case ADD in your reducer, seems like you only want to have id, field, content fields inside your note.查看减速器中的案例 ADD,似乎您只想在笔记中包含id, field, content字段。 But jsonplaceholder data does not contain a content field, so I'm adding some random string for that.但是 jsonplaceholder 数据不包含内容字段,所以我为此添加了一些随机字符串。

Change InitialUpdate case in your reducer like so.像这样更改减速器中的 InitialUpdate 大小写。 Because you're setting the state initially, you don't need to spread the state.因为您最初设置的是 state,所以不需要传播 state。

case "INITIALUPDATE":
      return payload.map(({ id, title }) => ({
          id,
          title,
          content:"Lorem, ipsum dolor sit"
        }))
      

Now inside useEffect on ListNotesScreen , after making axios request现在在useEffect上的ListNotesScreen中,发出 axios 请求后

if (response.status === 200) {
      // setData(response.data);
      dispatch({ type: "INITIALUPDATE", payload: response.data });

      setIsLoading(false);

      return;
    } else {
      throw new Error("Failed to fetch users");
    }

You should also use the state from context to view updated data.您还应该使用上下文中的 state 来查看更新的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM