如何将 JSON 对象数组中的项目添加到 Reducer 中的数组?
How to add the items from a array of JSON objects to an array in Reducer?
所以我正在从 https://jsonplaceholder.typicode.com/todos?_limit=10&page=1
中获取 10 个待办事项的列表
我正在用这 10 个待办事项的数组更新数据。我有一个动作类型为 INITIALUPDATE 的减速器,我想将 initialState 设置为待办事项列表。所以,现在 initialState 是一个空数组 [],但是在 dispatch 之后它应该和 data.
一样
列出备注屏幕
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;
};
查看减速器中的 ADD 大小写,似乎您只想在笔记中包含 id, field, content
字段。但是 jsonplaceholder 数据不包含内容字段,所以我为此添加了一些随机字符串。
像这样更改减速器中的 InitialUpdate 大小写。因为您最初是在设置状态,所以不需要传播状态。
case "INITIALUPDATE":
return payload.map(({ id, title }) => ({
id,
title,
content:"Lorem, ipsum dolor sit"
}))
现在在 ListNotesScreen
的 useEffect
内,发出 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");
}
您还应该使用上下文中的状态来查看更新的数据。
所以我正在从 https://jsonplaceholder.typicode.com/todos?_limit=10&page=1
中获取 10 个待办事项的列表我正在用这 10 个待办事项的数组更新数据。我有一个动作类型为 INITIALUPDATE 的减速器,我想将 initialState 设置为待办事项列表。所以,现在 initialState 是一个空数组 [],但是在 dispatch 之后它应该和 data.
一样列出备注屏幕
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;
};
查看减速器中的 ADD 大小写,似乎您只想在笔记中包含 id, field, content
字段。但是 jsonplaceholder 数据不包含内容字段,所以我为此添加了一些随机字符串。
像这样更改减速器中的 InitialUpdate 大小写。因为您最初是在设置状态,所以不需要传播状态。
case "INITIALUPDATE":
return payload.map(({ id, title }) => ({
id,
title,
content:"Lorem, ipsum dolor sit"
}))
现在在 ListNotesScreen
的 useEffect
内,发出 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");
}
您还应该使用上下文中的状态来查看更新的数据。