我一直在研究此错误已有2天了,但我似乎无法弄清楚这种错误的方式和原因。我的应用程序中有FlatList
个元素,其中ProductComponent
个元素,可以通过推送TouchableHighlight
中定义的ProductComponent
组件来买卖。
以下是我的FlatList
组件及其呈现的ProductComponent
的代码:
FlatList
组件:
const ProductList: React.FC = () => {
const energyResources = useSelector((state: RootState) => state.energyResources).asImmutable();
const dispatch = useDispatch<RootDispatch>();
const coins = useSelector((state: RootState) => state.coins).coins;
const purchaseItem = (item: IEnergyResource): void => {
if (coins > item.price) {
dispatch.energyResources.increaseAmountOwned(dispatch.energyResources, item);
dispatch.coins.buy(dispatch.coins, item.price);
Alert.alert(
'Gekocht!',
'Je hebt zojuist de energiebron ' + item.name + ' gekocht, ' +
'\nJe hebt nu nog €' + coins + ' Euro!'
);
} else {
Alert.alert(
'Niet gekocht',
'Sorry, je hebt niet genoeg geld om deze energiebron te kopen.'
);
}
};
const sellItem = (item: IEnergyResource): void => {
if (item.amountOwned > 0) {
dispatch.energyResources.decreaseAmountOwned(dispatch.energyResources, item);
dispatch.coins.sell(dispatch.coins, item.price);
Alert.alert(
'Verkocht!',
'De energiebron ' + item.name + ' is verkocht, ' +
'je hebt nu €' + coins + ' Euro.'
);
} else {
Alert.alert(
'Niet verkocht',
'Sorry, de energiebron ' + item.name + ' kon niet worden verkocht, ' +
'je hebt er geen in je bezit.'
);
}
};
return (
<FlatList
style={styles.list}
data={energyResources.toArray()}
renderItem={
({ item }) => <ProductComponent
resource={item}
onPurchase={purchaseItem}
onSell={sellItem}
canSell={item.amountOwned > 0}
/>
}
keyExtractor={(item) => item.name}
/>
);
}
买卖方法都在FlatList
组件中定义,然后传递给各个元素(我认为这比在ProductComponent
自身中定义功能并让每个渲染项更好)致电状态)。
ProductComponent
组件:
export interface IProductProps {
resource: IEnergyResource;
onPurchase: Function;
onSell: Function;
canSell: boolean;
}
const styles = StyleSheet.create({
buttonRight: {
alignItems: 'center',
alignSelf: 'flex-end',
backgroundColor: Constants.Colors.DodgerBlue,
marginVertical: 5,
padding: 10,
width: 150
},
image: {
alignSelf: 'flex-start',
height: 100,
width: 100
},
listItem: {
borderBottomColor: Constants.Colors.Blue,
borderBottomWidth: 2,
flex: 1,
flexDirection: 'row',
marginLeft: 5,
marginBottom: 0,
paddingBottom: 5
},
productInfo: {
width: 300,
},
rightButtons: {
alignItems: 'center',
alignSelf: 'flex-end'
},
sell: {
backgroundColor: Constants.Colors.Red
},
textLeft: {
alignSelf: 'flex-start',
fontSize: 20,
}
});
const ProductComponent: React.FC<IProductProps> = (props) => {
return (
<View style={styles.listItem}>
<Image source={props.resource.image.image} width={50} height={50} style={styles.image} />
<View style={styles.productInfo}>
<Text style={styles.textLeft}>{props.resource.name}</Text>
<Text style={styles.textLeft}>€{props.resource.price}</Text>
<Text style={styles.textLeft}>Energiewaarde: {props.resource.energyValue} Watt</Text>
<Text style={styles.textLeft}>In bezit: {props.resource.amountOwned}</Text>
</View>
<View style={styles.rightButtons}>
<TouchableHighlight style={styles.buttonRight} onPress={() => props.onPurchase(props.resource)}>
{/* eslint-disable-next-line react-native/no-inline-styles */}
<Text style={{ color: Constants.Colors.White, fontWeight: 'bold', fontSize: 15 }}>Kopen</Text>
</TouchableHighlight>
<TouchableHighlight style={[styles.buttonRight, styles.sell]} disabled={props.canSell} onPress={() => props.onSell(props.resource)}>
{/* eslint-disable-next-line react-native/no-inline-styles */}
<Text style={{ color: Constants.Colors.White, fontWeight: 'bold', fontSize: 15 }}>Verkopen</Text>
</TouchableHighlight>
</View>
</View>
);
};
该方法存在于IProductProps界面中,并且调用似乎可以正常工作(我正在获取定义的Alert
,好像我确实已经购买了产品一样)。但是,在警报框中单击 OK 后,指定产品(在ProductComponent
中定义为props.resource.amountOwned
的计数器仍然为0,我无法出售该产品。 / p>
这些是我在状态模型中定义的方法:
/**
* Increases the amount of items the player owns.
*
* @param {List<IEnergyResource>} state - the current state of the app
* @param {IEnergyResource} item - the item which was bought
* @returns {List<IEnergyResource>} state
*/
function increaseAmountOwned(state: EnergyResourcesState, item: IEnergyResource): EnergyResourcesState {
const itemIndex = state.indexOf(item);
const newItem = {
amountOwned: item.amountOwned++,
...item
};
return state.set(itemIndex, newItem);
}
/**
* Decreases the amount of items the player owns.
*
* @param {List<IEnergyResource>} state - The current state of the app
* @param {IEnergyResource} item - the item which was sold
* @returns {List<IEnergyResource>} state
*/
function decreaseAmountOwned(state: EnergyResourcesState, item: IEnergyResource): EnergyResourcesState {
const itemIndex = state.indexOf(item);
const newItem = {
amountOwned: item.amountOwned--,
...item
} as IEnergyResource;
return state.set(itemIndex, newItem);
}
const initialState: IEnergyResource[] =
[
{
name:'Windmolen',
price: 15,
energyValue:20,
environmentValue:-15,
image:{
maxSize:{
width:0.2,
height:0.2,
},
image: images.windmill,
},
amountOwned: 0,
amountTotal: 30,
amountPlaced: 0,
location:{
x:0.05,
y:0
},
},{
name:'Watermolen',
price: 15,
energyValue:15,
environmentValue:-10,
image:{
maxSize:{
width:0.2,
height:0.2,
},
image: images.turbine
},
amountOwned: 0,
amountTotal: 30,
amountPlaced: 0,
location:{
x:0.05,
y:0.3
},
},{
name:'Zonnepaneel',
price: 15,
energyValue:10,
environmentValue:-5,
image:{
maxSize:{
width:0.2,
height:0.2,
},
image: images.solarPanel
},
amountOwned: 0,
amountTotal: 30,
amountPlaced: 0,
location:{
x:0.3,
y:0
},
}
]
const resources = {
state: List(initialState),
reducers: {
place:(state: EnergyResourcesState, name: string): EnergyResourcesState =>
state = doMutateEnergyResource(state, name, true),
remove:(state: EnergyResourcesState, name: string): EnergyResourcesState =>
state = doMutateEnergyResource(state, name, false),
increaseAmountOwned: increaseAmountOwned,
decreaseAmountOwned: decreaseAmountOwned
},
};
我正在使用Rematch Redux framework处理该州。
这可能是我在这里忽略的一个小细节,因此非常感谢在正确方向上的任何帮助或推动。
提前谢谢!
答案 0 :(得分:0)
事实证明,我误解了Rematch Reducers与该州相关的工作方式。它们应被视为对已定义状态(在这种情况下为resources
的扩展方法)。从化简器的定义中可以看出,化简器有两个参数。当前状态以及要进行的任何更改。
据我了解,我需要为用户提供当前处于活动状态的状态(在本例中为FlatList
),就像这样:
dispatch.energyResources.increaseAmountOwned(dispatch.energyResources, item);
这是我的错误,因为state
参数由调用该方法时在后台由Rematch提供。该方法需要这样调用:
dispatch.energyResources.increaseAmountOwned(item);
重新匹配将注意到increaseAmountOwned()
的调用,并在执行之前将dispatch.energyResources
中存在的当前状态注入该方法。