React Native Category Tabs-각 탭은 다른 카테고리를 렌더링합니다.
현재 사용자가 해당 카테고리와 관련된 게시물을 렌더링하는 ScrollView에서 특정 카테고리를 선택할 수있는 탐색 화면을 구현하려고합니다.
내 API는 백엔드에서 모든 게시물 데이터를 가져오고 각 게시물에 대한 매개 변수 호출 categoryId가 있습니다.
내가하려는 것은 예를 들어 내 카테고리 중 하나가 스포츠 인 경우입니다. 사용자가 스포츠 탭을 선택하면 스포츠에 대한 모든 게시물이 포함 된 플랫리스트가 렌더링되어야합니다.
이 현재 구현에서는 카테고리 탭이 있으며 탭 중 하나를 선택하면 해당 특정 카테고리의 게시물이 아닌 모든 게시물이 렌더링됩니다.
내 코드는 다음과 같습니다.
function SearchScreen({ navigation }) {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const loadPosts = async () => {
setLoading(true);
const response = await postsApi.getPosts(page);
setLoading(false);
if (!response.ok) return setError(true);
setError(false);
setPosts(response.data);
};
const[page,setPage]=useState(0);
useEffect(() => {
loadPosts();
}, []);
const categories = [
{
label: "Sports",
id: 1,
},
{
label: "Fashion",
id: 2,
},
{
label: "News",
id: 3,
},
];
const[label,setLabel]=useState('Sports')
const[dataList,setDataList]=useState(posts)
const setLabelFilter=label=>{
setLabel(label)
}
return (
<>
<ActivityIndicator visible={loading} />
<Screen style={styles.screen}>
{error && (
<>
<View style={styles.error}>
<AppText>Could not retrieve posts from server.</AppText>
<AppButton title="Retry" onPress={loadPosts} />
</View>
</>
)}
<ScrollView
horizontal
style={{flexDirection:"row",
alignContent:"center",
width:Dimensions.get('window').width/1.05,
marginBottom:20,
}}
showsHorizontalScrollIndicator={false}
>
{categories.map(e=>(
<TouchableOpacity
style={[
{paddingHorizontal:10,paddingBottom:10},
label===e.label &&
{borderBottomWidth:3,
borderBottomColor:colors.primary,
borderRadius:2,
}
]}
onPress={()=>setLabelFilter(e.label)}
>
<AppText style={[{fontWeight:"500",color:colors.medium},label===e.label &&
{color:colors.primary,fontWeight:"700"}]}>{e.label}</AppText>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={posts} // to have all the data
keyExtractor={(post) => post.id.toString()}
renderItem={({ item,index }) => (
<Card
title={item.title}
subTitle={item.subTitle}
onPress={() => navigation.navigate(routes.POST_DETAILS, {post:item,index})}
/>
)}
/>
</Screen>
</>
);
}
console.log (posts)를 할 때 내 응답은 다음과 같습니다.
Object {
"Category": Object {
"id": 1,
"name": "Sports",
},
"categoryId": 3,
"createdAt": "2020-11-18T13:43:19.616Z",
"deletedAt": null,
"id": 506,
"subtTitle": "test",
"title": "test",
"updatedAt": "2020-11-23T06:57:44.150Z",
"userId": 1,
},
ID로 카테고리를 가져오고 각 특정 카테고리에 대한 모든 게시물을 포함하도록 API 호출을 변경하려고 생각했지만 작동하지 않았으므로 API 호출을 사용하여 모든 게시물을 가져 왔습니다.
최신 정보
const[label,setLabel]=useState('Sports')
const setLabelFilter=label=>{
setLabel(label)
}
const [currentCategoryId, setCurrentCategoryId] = useState()
const toggleBrands = (categoryId) => {
setCurrentCategoryId(categoryId)
setLabel(label)
};
return(
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
>
{categories.map(e=>(
<TouchableOpacity
key={e.id}
onPress={()=>{toggleBrands(e.id),
setLabelFilter(e.label)}}
selected={e.id === currentCategoryId}
>
<AppText>{e.label}</AppText>
</TouchableOpacity>
))}
</ScrollView>
<FlatList
data={currentCategoryId ?
posts.filter(post=>post.categoryId===currentCategoryId
):posts}
다음 코드를 시도해 보면 누군가 올바른지 여부를 알 수 있습니까?
답변
예를 들어, 먼저 화면 A의 플랫리스트 (모든 카테고리 표시)에서 항목을 클릭하면 시스템이 화면 B로 이동합니다 (플랫리스트에 선택한 카테고리의 항목 만 표시됨).
일반적인 방법은 선택한 범주의 데이터 만 동적으로 표시하는 것입니다 (예 : php 스크립트) (이 예에서는 sjson.php).
화면 A의 경우 다음과 같습니다.
Screen A GetFlatListItem 함수 :
GetFlatListItem (fruit_name) {
this.props.navigation.navigate('ScreenB', {unitserial: fruit_name})
}
Screen A Flatlist는 다음과 같을 수 있습니다.
data={ this.state.dataSource }
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem={({item}) =>
<View style={{flex: 1, flexDirection: 'row', justifyContent:'flex-start'}}>
<Text onPress={this.GetFlatListItem.bind(this, item.serial)} >
{item.ok}</Text>
</View>
화면 B의 경우 다음과 같습니다.
const enstring='https://www.test.com/sjson.php?serial=' + this.props.route.params.unitserial ;
return fetch(enstring)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
Flatlist는 다음과 같을 수 있습니다.
<FlatList
data={ this.state.dataSource }
>
필요에 맞게 코드를 수정해야합니다. 위는 예시 일뿐입니다.
먼저 상태 정의 :
const [apiRespPonse, setApiRespone] = useState("");
const [selectedTabData, setSelectedPost] = useState("");
const [category, setCategory] = useState("Sports");
API 호출에서 응답을 설정하십시오.
const fetchAllPost = () => {
setApiRespone([]);
const newArr = apiRespPonse.filter(obj => obj.label===category);
setSelectedPost(newArr)
};
렌더링 옵션의 경우 배열에 필터를 사용하여 선택한 탭 데이터를 가져옵니다.
return (
<View style={styles.app}>
<View style={styles.header}>
<View style={{ flexDirection: "row" }}>
{categories.map((item, index) => {
return <Text onPress={()=>{
setCategory(categories[index])
const newArr = apiRespPonse.filter(obj => obj.label===category);
setSelectedPost(newArr)
}} style={styles.title}>{item.label}</Text>;
})}
</View>
</View>
<FlatList
data={selectedTabData}/>
</View>
);
};
도움이 될 수 있습니다.
올바르게 이해했다면 선택한 카테고리로 단순 목록 콘텐츠를 새로 고치고 싶을 것입니다. 업데이트 전에 가지고있는 코드가 약간의 업데이트로 필요한 모든 것을 수행한다고 생각합니다. 다음은 업데이트해야하는 코드의 일부입니다.
{categories.map((e,index)=>(
<TouchableOpacity
...
style={[
...
index===page && {
borderBottomWidth:3,
borderBottomColor:colors.primary,
borderRadius:2,
}]
onPress={()=>{setPage(index)}}
>
...
</TouchableOpacity>
)}
postsApi.getPosts(page);
주어진 page
매개 변수 에 따라 올바른 데이터를 반환 하는지 확인하십시오 .