我对新的平面列表组件有意见.具体地说,它不会重新命名它的行,即使props 显示该行取决于更改.


FlatList docs说:

这是一个PureComponent,这意味着如果

THE QUESTION

然而,当我更改selectedCategory项的ID时——该props 应该指示行是否为"已 Select 的"——我认为props 应该重新命名.我弄错了吗?

我判断了列表和行组件的"componentWillReceiveProps"方法,列表可以很好地接收更新,但从未调用行的生命周期方法.

如果我在列表组件中包含一个随机的、无用的布尔状态值,并在props 更新时来回切换它,它就会工作——但我不知道为什么?

state = { updated: false };

componentWillReceiveProps(nextProps) {
  this.setState(oldstate => ({
    updated: !oldstate.updated,
  }));
}

<FlatList
  data={this.props.items.allAnimalCategories.edges}
  renderItem={this._renderRow}
  horizontal={true}
  keyExtractor={(item, index) => item.node.id}
  randomUpdateProp={this.state.updated}
/>

THE CODE

我的代码的 struct 是这样的:我有一个包含所有逻辑和状态的容器组件,其中包含一个平面列表组件(presentational,no state),它同样包含一个定制的presentational行.

Container
  Custom list component that includes the FlatList component
  (presentational, stateless) and the renderRow method
    Custom row (presentational, stateless)

容器包括以下组件:

 <CustomList
   items={this.props.viewer}
   onCategoryChosen={this._onCategoryChosen}
   selectedCategory={this.state.report.selectedCategory}
 />

客户列表:

class CustomList extends Component {
  _renderRow = ({ item }) => {
    return (
      <CustomListRow
        item={item.node}
        selectedCategory={this.props.selectedCategory}
        onPressItem={this.props.onCategoryChosen}
      />
    );
  };

  render() {
    return (
      <View style={_styles.container}>
        <FlatList
          data={this.props.items.categories.edges}
          renderItem={this._renderRow}
          horizontal={true}
          keyExtractor={(item, index) => item.node.id}
          randomUpdateProp={this.state.updated}
        />
      </View>
    );
  }

}

(数据来自继电器)

最后一行:

render() {
    const idsMatch = this.props.selectedCategory.id == this.props.item.id;
    return (
      <TouchableHighlight onPress={this._onItemPressed}>
        <View style={_styles.root}>
          <View style={[
              _styles.container,
              { backgroundColor: this._getBackgroundColor() },
            ]}>
            {idsMatch &&
              <Image
                style={_styles.icon}
                source={require('./../../res/img/asd.png')}
              />}
            {!idsMatch &&
              <Image
                style={_styles.icon}
                source={require('./../../res/img/dsa.png')}
              />}
            <Text style={_styles.text}>
              {capitalizeFirstLetter(this.props.item.name)}
            </Text>
          </View>
          <View style={_styles.bottomView}>
            <View style={_styles.greyLine} />
          </View>
        </View>
      </TouchableHighlight>
    );
  }

这一行没有那么有趣,但我加入它是为了表明它完全是无状态的,并且依赖于它的父母props .

状态更新如下:

_onCategoryChosen = category => {
    var oldReportCopy = this.state.report;
    oldReportCopy.selectedCategory = category;
    this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
  };

该州的情况如下:

state = {
    ...
    report: defaultStateReport,
  };

const defaultStateReport = {
  selectedCategory: {
    id: 'some-long-od',
    name: '',
  },
  ...
};

推荐答案

这里的问题在于

  1. 您正在对现有的状态切片进行变异,而不是创建变异的副本

_onCategoryChosen = category => {
    var oldReportCopy = this.state.report; // This does not create a copy!
    oldReportCopy.selectedCategory = category;
    this.setState(Object.assign({}, this.state, { report: oldReportCopy }));
};

这应该是

_onCategoryChosen = category => {
    var oldReportCopy = Object.assign({}, this.state.report);
    oldReportCopy.selectedCategory = category;
    // setState handles partial updates just fine, no need to create a copy
    this.setState({ report: oldReportCopy });
};

  1. FlatList的props 保持不变,您的_renderRow函数可能依赖于selectedCategoryprops ,该props 会发生变化(如果不是因为第一个错误),但FlatList组件不知道这一点.要解决这个问题,请使用extraDataprops .

     <FlatList
       data={this.props.items.categories.edges}
       renderItem={this._renderRow}
       horizontal={true}
       keyExtractor={(item, index) => item.node.id}
       extraData={this.props.selectedCategory}
     />
    

React-native相关问答推荐

解除渲染和重新渲染后如何保持我的组件状态?

导航到另一个屏幕后清空搜索屏幕

使用下拉菜单时react 本机react-native-dropdown-select-list,它会将下面的项目向下移动.如何阻止这种情况发生

将值从一个 js 文件传递​​到 react native 中的另一个 js 文件:react native

到达安装依赖项时 EAS 构建错误

使用react native 杀死应用程序后蓝牙仍处于活动状态

为什么将字符串写入文件然后将相同的文件作为字符串读取会导致不同的字符串?

React Native - React Native 架构

如何修复 React Native 中任务:app:processDebugManifest的执行失败?

如何在 React-Native 中创建检测自动位置的map

中彼此相邻对齐(Align) react native

无法访问函数内部的状态

Undefined 不是判断 this.state.* 的对象

如何在 React Native 中获取 TextInput 相对于其父级或屏幕的光标位置

React-Native Android 中隐藏(hide)的元素溢出

如何在 React Native 中使用 Jest

React-native Awesome 元素没有构建 android 元素

如何将 jest 测试移动到 /test 文件夹并让它们运行?

react-native iOS 应用在部署后不显示静态/本地资源

StackNavigator中如何改变动画的方向?