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

React多同类型Sorting组件仅最后一个DOM更新问题排查求助

问题解决:多个Sorting子组件仅最后一个更新的原因与修复

核心问题原因

你在父组件中使用了**单个React.createRef()**绑定所有子组件,当通过map循环渲染多个<Sorting>时,这个ref会被逐个覆盖,最终只会指向最后一个渲染完成的子组件。所以调用this.child.current.fillArray()时,只有最后一个子组件会执行更新逻辑。

另外还有两个次要问题:

  • 子组件没必要把props的array存到自己的state里,完全可以直接使用props值,这样父组件array更新时子组件会自动同步渲染
  • componentDidMount里的await this.resetTheArray()无效,因为resetTheArray里的setState是异步操作,不会返回Promise,await不会等待它完成

修复方案

方案1:使用数组存储所有子组件的ref(保留子组件fillArray方法)

修改父组件代码,用数组保存每个子组件的ref,调用时遍历所有ref触发更新:

class MainPage extends Component {
    constructor(props) {
        super(props);
        this.state = {
            array: [],
            temp: [1, 2, 3]
        };
        // 用数组存储所有子组件的ref
        this.childRefs = [];
    }

    randomNumber(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min) + min);
    }

    componentDidMount() {
        this.resetTheArray();
    }

    resetTheArray() {
        const temp = [];
        for (let i = 0; i < 15; i++) {
            temp.push(this.randomNumber(5, 750));
        }
        this.setState({ array: temp });
    }

    onClickFillArray = () => {
        // 遍历所有子组件ref,调用fillArray
        this.childRefs.forEach(child => child.fillArray());
    }

    render() {
        return (
            <div>
                <NavBar />
                {this.state.temp.map((e) => (
                    <Sorting 
                        key={e} 
                        // 将每个子组件的ref存入数组
                        ref={(el) => this.childRefs.push(el)} 
                        id={e} 
                        array={[...this.state.array]} 
                    />
                ))}
                <button onClick={this.onClickFillArray}>click here</button>
                <button onClick={() => this.onClickBubbleSort()}>Sort me </button>
            </div>
        );
    }
}

方案2:优化子组件,直接依赖props自动更新(更推荐)

子组件不需要自己维护array状态,直接使用props传递的array,这样父组件array更新时,所有子组件会自动重新渲染,省去手动调用fillArray的步骤:

修改子组件代码:

class Sorting extends Component {
  constructor(props) {
    super(props);
    this.state = {
      bars: NumberOfBars,
      firstSelection: "Insertion",
      btn: false,
      dual: true,
    };
    this.bubbleSort = this.bubbleSort.bind(this);
  }

  // 移除fillArray方法,不再将array存入子组件state

  render() {
    // 直接使用props中的array
    const { array } = this.props;

    return (
      <Container>
        <h1>{`component-${this.props.id}`}</h1>
        <div className="theContainer">
          {array.map((value, idx) => (
            <div
              className={"theBar " + this.props.id}
              key={idx}
              style={{ height: `${value}px` }}
            ></div>
          ))}
        </div>
        <button onClick={this.bubbleSort}>sort</button>
        {/* reset按钮直接调用父组件的重置方法 */}
        <button onClick={this.props.onReset}>reset</button>
      </Container>
    );
  }
}

父组件修改,传递onReset方法:

class MainPage extends Component {
    // ... 其他代码不变

    render() {
        return (
            <div>
                <NavBar />
                {this.state.temp.map((e) => (
                    <Sorting 
                        key={e} 
                        id={e} 
                        array={[...this.state.array]}
                        onReset={() => this.resetTheArray()}
                    />
                ))}
                <button onClick={() => this.resetTheArray()}>click here</button>
                <button onClick={() => this.onClickBubbleSort()}>Sort me </button>
            </div>
        );
    }
}

额外说明

  • 方案2更符合React的数据流设计:父组件维护状态,子组件仅负责渲染和交互,避免了不必要的状态同步问题
  • 父组件中resetTheArray里的this.setState({ array: temp })是异步的,如果需要在数组更新后做某些操作,可以使用setState的回调:
resetTheArray() {
    const temp = [];
    for (let i = 0; i < 15; i++) {
        temp.push(this.randomNumber(5, 750));
    }
    this.setState({ array: temp }, () => {
        // 数组更新完成后的操作
        console.log("array updated:", this.state.array);
    });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 02:00:02