我花了好几个小时来处理这个bug,我希望另一双眼睛可以帮助我!感谢你的帮助!
我有一个React Native应用程序,在Modal中,我有一个带单选按钮的选项列表。
我想要的:
当您单击模型列表中的TouchableHighlight项目时,我希望单选按钮移动到用户按下的项目。换句话说,如果我按下我单击的项目的rowId,我想将单选按钮设置为selected
。
发生了什么: 当我关闭Modal并重新打开时,我看到单选按钮已移动到正确的选项,但问题是当我点击时我需要立即移动单选按钮!所以,我正在设置正确的状态,但在重新打开Modal之前,组件不会重新渲染。
这是我的自定义单选按钮组件:
export default RadioButton = ({style, selected}) => {
return (
<View style={[{
height: 24,
width: 24,
borderRadius: 12,
borderWidth: 2,
borderColor: colors.primaryText,
alignItems: 'center',
justifyContent: 'center',
}, style]}>
{
selected ?
<View style={{
height: 16,
width: 16,
borderRadius: 8,
backgroundColor: colors.primaryText,
}}/>
: null
}
</View>
);
}
我有一个处理状态的容器组件:
class ShippingDetails extends Component {
constructor(props){
super(props)
const ds = new ListView.DataSource({rowHasChanged: (r1, r2, ) => r1 !== r2 });
const deliveryOptions = ['USPS Mail', 'USPS Next Day'] //will be replaces with redux
this.state = {
dataSource: ds.cloneWithRows(deliveryOptions),
shippingMethod: null,
modalVisible: false,
selectedOption: 0
};
}
_handleShippingMethodPress = (selected, id) => {
this.setState({shippingMethod: selected})
this.setState({selectedOption: id})
}
renderShippingMethods = (shippingMethod, sectionID, rowID, highlightRow) => {
return (
<SelectShippingMethod
onPress={() => this._handleShippingMethodPress(shippingMethod, rowID)}
shippingMethod={shippingMethod}
price={'Free Shipping'}
date={'Expected delivery March 12'}
selected={this.state.selectedOption == rowID}
/>
)
}
render () {
return (
<View style={backgroundApp}>
<View>
<SelectShippingMethod
shippingMethod={shippingMethod}
onPress={() => this.setModalVisible(true)}
price={'Free Shipping'} //replace with redux price
date={'Expected delivery March 12'}
singleRow={true}
/>
<Modal
animationType={"slide"} //slide and fade
transparent={false}
visible={this.state.modalVisible}
onRequestClose={()=>{console.warn('callback for onRequestClose Modal in ShippingDetails')}} //
>
<ShippingMethodOptions
dataSource={this.state.dataSource}
renderRow={this.renderShippingMethods}
renderSeparator={Separator}
closeModal={() => this.setModalVisible(false)}
/>
</Modal>
</View>
</View>
)
}
}
SelectShippingMethod是一个返回单个TouchableHighlight项目的组件,并从容器组件传递selected
作为prop。
return(
<TouchableHighlight
onPress={onPress}>
<View style={[rowWrapper, {alignItems: 'center', paddingLeft: 5}]}>
{ !singleRow && <RadioButton selected={selected}/>}
<View style={styles.methods}>
<Text style={descriptionColor}>{description}</Text>
<Text style={subHeader}>{shipDate}</Text>
</View>
<Text style={styles.price}>{shipPrice}</Text>
{/*<Icon name="ios-arrow-forward" size={17} color={colors.iconGrey} style={arrows}/>*/}
</View>
</TouchableHighlight>
)
ShippingMethodOptions是一个包装ListView的组件,并传递相应的道具。
const ShippingMethodOptions = ({dataSource, renderRow, renderSeparator, closeModal}) => {
return(
<View style={backgroundApp}>
<NavHeader closeModal={closeModal}/>
<Text style={[subHeader, textSection]}></Text>
<View style={hr}></View>
<ListView
dataSource={dataSource}
renderRow={renderRow}
renderSeparator={renderSeparator}
/>
</View>
)
}
我注意到当我用光纤升级到React 16时,单选按钮按预期工作,所以这让我想到了一些事情。
光纤速度快得多,我可以编写更多的代码吗?
使用更新的React版本时,Modal组件中的生命周期方法有什么不同吗?
有什么不同的setState会导致更多东西用光纤重新渲染?
更新
我已经控制台记录了这个过程,我看到按下一个项目后,ListView上的renderRow不会被再次调用,而是选择了undefined
来调用SelectedShippingMethod。为什么会发生这种情况?如何才能实现这一目标?