英文:
How to return propertie from sub array object with react native?
问题
export const SubCategoryScreen = () => {
const { subCategoryList } = useContext(CategoryContext);
return (
<SafeArea>
<CategoryList
data={subCategoryList[0]} // Access the array directly
renderItem={({ item }) => {
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard category={item} /> {/* Pass item directly, not item.subcategories */}
</Spacer>
);
}}
keyExtractor={(item) => item.id.toString()} {/* Ensure item.id is a string */}
/>
</SafeArea>
);
};
英文:
I have a react native app. And I try to show the name and image on a card.
So this is the service:
export const fetchSubCategoryData = async () => {
try {
const response = await fetch("http://192.168.1.68:8000/api/categories/2", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
export const subCategoryTransform = ({ results = [] }) => {
const mappedResults = results.map((subcategories) => {
subcategories.images = subcategories.images;
return {
...subcategories,
name: subcategories.name,
};
});
return mappedResults;
};
the context:
export const CategoryContextProvider = ({ children }) => {
const [categoryList, setCategoryList] = useState([]);
const [subCategoryList, setSubCategoryList] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [] = useState([]);
const retrieveSubCategories = () => {
setLoading(true);
setTimeout(() => {
fetchSubCategoryData()
.then(subCategoryTransform)
.then((results) => {
setLoading(false);
setSubCategoryList([results]);
})
.catch((err) => {
setLoading(false);
setError(err);
});
});
};
useEffect(() => {
retrieveCategories();
}, []);
useEffect(() => {
retrieveSubCategories();
}, []);
return (
<CategoryContext.Provider
value={{
categoryList,
subCategoryList,
loading,
error,
}}>
{children}
</CategoryContext.Provider>
);
};
And the component where I want to show the name and the image:
export const SubCategoryScreen = () => {
const { subCategoryList } = useContext(CategoryContext);
return (
<SafeArea>
<CategoryList
data={subCategoryList}
renderItem={({ item }) => {
console.log(item.subcategories);
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard category={item.subcategories} />
</Spacer>
);
}}
keyExtractor={(item) => item.subcategories}
/>
</SafeArea>
);
};
And the api call of http://192.168.1.68:8000/api/categories/2/ looks:
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"id": 2,
"name": "vogels",
"description": "vogels",
"legislation": "",
"review": "",
"eaza": "",
"images": "http://192.168.1.68:8000/media/photos/categories/birds.png",
"animals": [],
"subcategories": [
{
"id": 3,
"name": "roofvogels",
"description": "roofvogels",
"images": "http://192.168.1.68:8000/media/photos/categories/predator_ETI4KPC.jpg"
},
{
"id": 5,
"name": "parkieten",
"description": "parkieten",
"images": "http://192.168.1.68:8000/media/photos/categories/predator_gqLXVoK.jpg"
}
],
"category": null
}
And then I want to show the name and images of the subcategories. So in this case:
roofvogels and parkieten.
But I get this error:
Warning: Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.%s,
Check the render method of `VirtualizedList`., ,
CellRenderer@http://192.168.1.68:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&hot=false&strict=false&minify=false:82071:36
in VirtualizedList (created by FlatList)
Question: How to return the name and images of the subcategories object?
I try this:
export const SubCategoryScreen = () => {
const { subCategoryList } = useContext(CategoryContext);
return (
<SafeArea>
<CategoryList
data={subCategoryList}
renderItem={({ item }) => {
console.log(item.subcategories);
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard category={item.subcategories} />
</Spacer>
);
}}
keyExtractor={(item) => item.id}
/>
</SafeArea>
);
};
But still:
Warning: Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.%s,
Check the render method of `VirtualizedList`., ,
CellRenderer@http://192.168.1.68:19000/node_modules%5Cexpo%5CAppEntry.bundle?platform=android&dev=true&hot=false&strict=false&minify=false:82071:36
in VirtualizedList (created by FlatList)
And so this is the component when the app is first time loading. This is the main screen. And from there the user can navigate to a subcategorie card:
import { ActivityIndicator, MD2Colors } from "react-native-paper";
import { FlatList, Pressable, SafeAreaView, StatusBar } from "react-native";
import React, { useContext } from "react";
import { CategoryContext } from "../../../services/category/category.context";
import { CategoryInfoCard } from "../components/category-info-card.component";
import { MD3LightTheme as DefaultTheme } from "react-native-paper";
import { Search } from "../components/search.component";
import { Spacer } from "../../../components/spacer/spacer.component";
import { TouchableOpacity } from "react-native-gesture-handler";
import styled from "styled-components/native";
const SafeArea = styled(SafeAreaView)`
flex: 1;
${StatusBar.currentHeight && `margin-top: ${StatusBar.currentHeight}px`};
`;
export const CategoryList = styled(FlatList).attrs({
contentContainerStyle: {
padding: 16,
},
})``;
const Loading = styled(ActivityIndicator)`
margin-left: -25px;
`;
const LoadingContainer = styled.View`
position: absolute;
top: 50%;
left: 50%;
`;
export const CategoryScreen = ({ navigation }) => {
const { loading, error, categoryList } = useContext(CategoryContext);
return (
<SafeArea>
{loading && (
<LoadingContainer>
<ActivityIndicator animating={true} color={MD2Colors.green200} />
</LoadingContainer>
)}
<Search />
<CategoryList
data={categoryList}
renderItem={({ item }) => {
return (
<TouchableOpacity
onPress={() => navigation.navigate("groepen", { subcategories: item.id })}>
<Spacer position="bottom" size="large">
<CategoryInfoCard category={item} />
</Spacer>
</TouchableOpacity>
);
}}
keyExtractor={(item) => item.name}
/>
</SafeArea>
);
};
If I do this:
const retrieveSubCategories = () => {
setLoading(true);
setTimeout(() => {
fetchSubCategoryData()
//.then(subCategoryTransform)
.then((results) => {
setLoading(false);
setSubCategoryList([results]);
})
.catch((err) => {
setLoading(false);
setError(err);
});
});
};
Then I see in the console.log:
return (
<SafeArea>
<CategoryList
data={subCategoryList}
renderItem={({ item }) => {
console.log("SUBCATEGORES", item.subcategories);
return (
<Spacer position="bottom" size="large">
<CategoryInfoCard category={item.subcategories} />
</Spacer>
);
}}
keyExtractor={(item) => item.id}
/>
</SafeArea>
);
SUBCATEGORES Array [
Object {
"description": "roofvogels",
"id": 3,
"images": "http://192.168.1.68:8000/media/photos/categories/predator_ETI4KPC.jpg",
"name": "roofvogels",
},
Object {
"description": "parkieten",
"id": 5,
"images": "http://192.168.1.68:8000/media/photos/categories/predator_gqLXVoK.jpg",
"name": "parkieten",
},
]
So this is correct.
This is the complete service:
export const fetchCategoryData = async () => {
try {
const response = await fetch("http://192.168.1.68:8000/api/categories/main_groups/", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
export const fetchSubCategoryData = async () => {
try {
const response = await fetch("http://192.168.1.68:8000/api/categories/2", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return await response.json();
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
export const categoryTransform = ({ results = [] }) => {
const mappedResults = results.map((categoryList) => {
categoryList.images = categoryList.images;
return {
...categoryList,
name: categoryList.name,
};
});
return mappedResults;
};
export const subCategoryTransform = ({ results = [] }) => {
const mappedResults = results.map((subcategories) => {
subcategories.subcategories.images = subcategories.subcategories.images;
return {
...subcategories,
name: subcategories.name,
};
});
return mappedResults;
};
I have one main screen with url:
> http://192.168.1.68:8000/api/categories/main_groups/
And from here you can navigate to a subcategory:
subscreen with url:
> http://192.168.1.68:8000/api/categories/2
答案1
得分: 1
你不能使用对象作为键 - 它应该是一个字符串。在你的CategoryList中,你有:
keyExtractor={(item) => item.subcategories}
尝试使用
keyExtractor={(item) => item.id}
英文:
You can't use an object as a key - it should be a string. In your CategoryList, you have
keyExtractor={(item) => item.subcategories}
Try using
keyExtractor={(item) => item.id}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论