Home > Software design >  How to add the items from a array of JSON objects to an array in Reducer?
How to add the items from a array of JSON objects to an array in Reducer?

Time:05-07

So I am fetching the list of 10 todos from https://jsonplaceholder.typicode.com/todos?_limit=10&page=1

I am updating data with the array of these 10 todos. I have a reducer with action type INITIALUPDATE which I want to set the initialState to the list of todos. So, now initialState is an empty array [], but after the dispatch it should be the same as 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

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;
};

CodePudding user response:

Looking at case ADD in your reducer, seems like you only want to have id, field, content fields inside your note. But jsonplaceholder data does not contain a content field, so I'm adding some random string for that.

Change InitialUpdate case in your reducer like so. Because you're setting the state initially, you don't need to spread the state.

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

Now inside useEffect on ListNotesScreen, after making axios request

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.

  • Related