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.