You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中getDerivedStateFromProps同步props与含搜索栏组件state异常

问题诊断

同步失效是两个核心逻辑错误导致的:

  • getDerivedStateFromProps判断逻辑完全错误:当前代码对比的是props.data和state.data,但state.data会被搜索功能修改为过滤后的结果集,只要用户执行过搜索,二者永远不相等,会导致每次渲染都直接用props覆盖搜索结果;同时你没有留存上一次接收的props数据引用,根本无法区分数据变化是来自Redux的props更新,还是本地搜索修改了state。
  • 原始数据备份arrayholder仅在构造函数中赋值一次,后续Redux推送新的props.data时,这个备份变量从未同步更新,搜索逻辑永远基于初始加载的老数据过滤。
  • 额外提个性能问题:你把Item组件定义在render方法内部,每次渲染都会重新生成全新的组件引用,React会判定组件类型变化,触发不必要的卸载重挂载,浪费性能。
修复方案

在state中单独新增字段存储上一次从props接收的原始数据引用,作为props是否真的更新的判断依据,不要直接拿props和可能被本地修改过的展示用state做对比。当检测到props.data真实更新时,同步更新state中的展示数据、标记位,同时更新实例上的原始数据备份,保证搜索逻辑使用最新的原始数据源。
如果需要props更新后保留用户当前输入的搜索关键词,在数据更新后重新执行一次过滤逻辑即可;不需要的话直接清空搜索状态。

修正后的核心代码如下:

// 将Item组件移到类外部定义,避免render内重复创建
const Item = ({ nom_shotgun, cle, photo_shotgun, date_shotgun, etat, admin, onLongPress, onPress, renderAdmin }) => {
  const handlerLongClick = () => {
    Alert.alert(
      "Alert",
      "Supprimer le shotgun?",
      [
        { text: "oui", onPress: () => onLongPress(cle) },
        { text: "non", onPress: () => console.log("no Pressed") }
      ]
    );
  };
  return (
    <TouchableOpacity style={styles.item} onPress={onPress} onLongPress={handlerLongClick}>
      <View>
        <Text style={styles.nom_shotgun}>{nom_shotgun}</Text>
        <Text style={styles.date_shotgun}>{date_shotgun}</Text>
        {renderAdmin(admin)}
        <Text style={styles.etat}> {etat} </Text>
        <Image
          style={styles.photo_shotgun}
          source={require('../image/shotgun2.png')}
        />
        <Divider style={{ height: 1 }} />
      </View>
    </TouchableOpacity>
  )
}

class modification extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      cle: props.cle,
      nom_shotgun: props.nom_shotgun,
      date_shotgun: props.date_shotgun,
      photo_shotgun: props.photo_shotgun,
      etat: props.etat,
      admin: props.admin,
      error: null,
      searchValue: "",
      data: props.data,
      // 存储上一次从props接收的原始数据,用于更新判断
      lastPropsData: props.data,
      loading: false,
    };
    // 初始化原始全量数据备份
    this.arrayholder = props.data;
  }

  searchFunction = (text) => {
    const updatedData = this.arrayholder.filter((item) => {
      const item_data = `${item.nom_shotgun.toUpperCase()})`;
      const text_data = text.toUpperCase();
      return item_data.indexOf(text_data) > -1;
    });
    this.setState({ data: updatedData, searchValue: text });
  };

  static getDerivedStateFromProps(props, state) {
    // 仅对比当前props数据和上次存储的props快照,不和本地修改过的展示数据对比
    if (props.data !== state.lastPropsData) {
      return {
        lastPropsData: props.data,
        data: props.data,
        // 不需要props更新后保留搜索内容就保留这行,需要就删掉
        searchValue: ""
      };
    }
    return null
  }

  componentDidUpdate(prevProps) {
    // getDerivedStateFromProps是静态方法无法访问实例this,在这里同步更新实例上的全量数据备份
    if (prevProps.data !== this.props.data) {
      this.arrayholder = this.props.data;
      // 如果需要保留当前搜索关键词,打开下方注释,用新的全量数据重新执行过滤
      // if (this.state.searchValue) {
      //   this.searchFunction(this.state.searchValue)
      // }
    }
  }

  _supprimer = (cle) => {
    // 原有删除逻辑
  }

  _navigation = (etat, admin) => {
    // 原有页面跳转逻辑
  }

  _admin = (admin) => {
    // 原有管理员状态渲染逻辑
  }

  render() {
    const { etat, admin } = this.props;
    return (
      <View>
        {/* 搜索输入框绑定searchFunction即可 */}
        {/* 列表渲染注意传入正确参数,示例:
        <FlatList
          data={this.state.data}
          renderItem={({ item }) => (
            <Item
              nom_shotgun={item.nom_shotgun}
              cle={item.cle}
              photo_shotgun={item.photo_shotgun}
              date_shotgun={item.date_shotgun}
              etat={item.etat}
              admin={item.admin}
              onLongPress={this._supprimer}
              onPress={() => this._navigation(etat, admin)}
              renderAdmin={this._admin}
            />
          )}
          keyExtractor={item => item.cle}
        />
        */}
      </View>
    );
  };
}

几个注意点:

  • 用独立字段存props快照是React官方推荐的getDerivedStateFromProps派生状态受控场景的标准写法,完全避开了生命周期废弃的问题,也能正确区分props更新和本地state修改。
  • 原来render里定义的Item组件没有返回JSX结构,事件方法也没有正确绑定实例this,移到外部后通过props传入回调即可解决this指向问题。
  • 如果你的数据是数组,尽量保证Redux更新数据时返回新的数组引用,不然引用不变的话!==判断会识别不到更新,这也是Redux immutable更新的基本要求。

内容的提问来源于stack exchange,提问作者ZHOU Alec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:33:17