React Native Modal - setState不够快吗?

时间:2017-05-05 20:27:01

标签: javascript reactjs react-native setstate react-fiber

我花了好几个小时来处理这个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时,单选按钮按预期工作,所以这让我想到了一些事情。

  1. 光纤速度快得多,我可以编写更多的代码吗?

  2. 使用更新的React版本时,Modal组件中的生命周期方法有什么不同吗?

  3. 有什么不同的setState会导致更多东西用光纤重新渲染?

  4. 更新 我已经控制台记录了这个过程,我看到按下一个项目后,ListView上的renderRow不会被再次调用,而是选择了undefined来调用SelectedShippingMethod。为什么会发生这种情况?如何才能实现这一目标?

0 个答案:

没有答案