我有嵌套的商品目录 . 它有一些类别,可以引导您到另一个类别和类别,这些类别和类别会引导您使用该组的商品页面进行分页 . 我不知道它是如何完成的,我决定做以下事情 . 当用户点击最终类别(跟随一组商品)时,我将他导航到组件 **** . 它显示任何类别ID的商品列表 . 此组件连接到redux存储 . 它仅从redux商店获取所有数据 . 我有一个单独的货物减速机 . 这个reducer ' initial state is null when you start app the first time. I don't想要将整个目录预加载到商店,我想部分地做 . 点击商品类别后,用户会重定向到具有类别ID参数的GoodsList组件 . 然后GoodsList从这个特定类别的远程服务器商品列表下载(如果它还没有存储,除此之外的所有商品卡将根据下载的数据显示)并且当组件连接到商店(并且数据是已更新的组件已重新显示,并显示了货物清单 . 问题是,第一个第一次组件呈现的商品集是空的,然后在其构造函数中更新数据 - >组件重新呈现,然后我才能获得我可以在屏幕上显示的数据集 . 当用户点击特定类别但是在显示货物的组件被挂载之前,我该如何部分填充redux商店(商品)?我可以在加载数据时显示微调器,但为什么我需要渲染两次组件 . 或者......还有其他想法吗?
Update. If the question above is hard to understand, see info below.
CatalogComponent.js
/* necessary imports */
import categories from 'appcontent/categories'; // initial categories
const CatalogComponent = () => {
return (
<ScrollView>
<View style={styles.container}>
// If there is no passed categories for current component, using base set of categories (the whole catalog).
// ReactNavigation is used. Navigation prop is from there.
<CatalogList categories={!!props.navigation.state.params ? props.navigation.state.params.categories : categories}/>
</View>
</ScrollView>
)
}
categories.js
const goods = [
{
"id": 1,
"title": "First cat",
"subs": [
{
"id": 11,
"title": "First subcat",
"subs": [
{
"id": 111,
"title": "first final cat",
"subs": null
},
{
"id": 112,
"title": "first final cat",
"subs": null
},
],
},
],
},
{
"id": 2,
"title": "Second cat",
"subs": null
},
]
export default goods;
CatalogList.js
const CatalogList = (props) => {
const { categories } = props;
return (
<View>
{
// Render each element of current catalog level and passin
categories.map((item) => {
return <CatalogItem key={item.title} categories={item} />
})
}
</View>
);
}
CatalogItem.js
const onPress = (item, navigation) => {
navigation.navigate({
routeName: 'CatalogComponent',
params: { categories: item.subs, title: item.title }, // this categories is props.navigation.state.params.categories in CatalogComponent
key: Math.random() * 10000 // needed for I could open the same Route with new paarmeters
})
};
const CatalogItem = (props) => {
const { id, title, subs } = props.categories;
return (
<TouchableOpacity
onPress={() => {
if (props.categories.subs !== null && props.categories.subs.length > 0) {
// Redirect to the very first route (component) CatalogComponent with new categories parameter (child catalog list for current category)
onPress(props.categories, props.navigation); // props.navigation is for redirect purposes using ReactNavigation
} else {
// Show the list of goods for category of ID equals id
// THE MAIN PART OF QUESTION STARTS FROM HERE
props.navigation.navigate({
routeName: 'GoodsList',
params: { categoryId: 123 },
})
}
//props.categories.subs !== null && props.categories.subs.length>0 && onPress(props.categories, props.navigation)
}}
>
<View style={styles.container}>
<Text style={styles.text}>{title}</Text>
<Icon style={styles.arrow} name="chevron-right" size={20} color="gray" />
</View>
</TouchableOpacity>
);
}
GoodsList.js
/* Necesary imports */
import goodsList from 'appcontent/goods';
class GoodsList extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true
}
}
componentWillUnmount() {
clearTimeout();
}
componentWillMount() {
// Setting of category to state
this.catId = this.props.navigation.state.params.categoryId;
// Imitate fetching data from remote server by setting timeout
setTimeout(() => {
// "Fetching" data
this.goods = goodsList[this.catId];
// The first thing I do is save data to Redux store. Render method below gets data from Redux.
this.props.dispatch(goodsFill({ goods: this.goods, catId: this.catId })); // the reducer code is below
this.setState((curState) => {
return {
...curState,
loading: 0
}
});
}, 5000);
}
render() {
const { goods } = this.props;
console.log('settingGoodsList', goods.goods); // !!!
return (
<View style={styles.container}>
{
this.state.loading && <Text>Loading</Text>
}
{
goods.goods[this.catId] && goods.goods[this.catId].map((item, index) => {
console.log(item);
return <Text key={item[Object.keys(item)[0]].name}>{item[Object.keys(item)[0]].name}</Text>
})
}
</View>
);
}
}
减速器
const initReducerDefaultState = {
goods: {}
};
export default (state = initReducerDefaultState, action) => {
switch (action.type) {
case 'GOODS_FILL':
return {
...state, goods: { ...state.goods, [action.catId]: action.goods }
}
default:
return state;
}
}
行动顺序 . 您输入目录页面CatalogComponent . 你第一次看到整个目录(它的顶级类别) . 单击某些项目后,您将使用其子类别等进入下一级别 . 从技术上讲,您将重定向到相同的路径,但这次使用的是从之前传递的类别 . 如果该类别是最终的(它没有子类别,它应该跟随您到其商品列表) . 但是,当首次打开具有特定categoryId的GoodsList时,我想获取数据(此类别的商品)并首先将其保存到redux存储(仅当此类别没有数据时,代码中没有这样的检查,但我'将它包括在内) . 只有在该组件从Redux(不是直接从远程服务器)获取数据并呈现它之后 . 同时我向用户展示微调器 .
在GoodsList中,您可以看到console.log('settingGoodsList',goods.goods);问题是它叫了两次 . 第一次 - 渲染组件时 . 第二次 - 获取数据,更改存储,并自动重新呈现组件.js这是一个问题,这是获取远程数据工作的方式还是我做错了什么?我首先应该获取数据,然后组件应该呈现其内容 . 我认为componentWillMount()是可以帮助我的地方 . 它在渲染功能之前调用 . 但是console.log()输出两次信息 .