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

React-redux中JSX内函数组件无法随props更新重渲染问题

问题根源:MultiChoice 组件未同步 props 更新

你遇到的问题核心在于 MultiChoice 组件将 props 数据存入 state 后,没有在 props 更新时同步更新 state。具体来说:

  1. 当 Redux 状态更新后,App 组件的 this.props.question 确实更新了,render 方法也会重新执行,并且向 MultiChoice 传入了新的 questionContent props。
  2. 但 MultiChoice 的 question 和 answerArray 状态是在 constructor 中初始化的——而 constructor 仅在组件首次挂载时执行一次。后续 props 变化时,state 不会自动同步,所以组件依然使用旧的 state 数据渲染,看起来就像没更新。

解决方案:直接使用 props 或同步 props 到 state

方案一:直接使用 props(推荐)

既然 question 和 answerArray 是从父组件传入的动态数据,完全没必要存入 state,直接使用 props 即可。仅将需要组件内部管理的状态(比如选中的答案 ID、提示信息)保留在 state 中。

修改后的 MultiChoice 代码:

import React, { Component } from 'react';
import ReactHtmlParser from 'react-html-parser';
import './questions.css';

class MultiChoice extends Component {
  constructor(props) {
    super(props);
    // 只保留组件内部需要管理的状态
    this.state = {
      selectedAnswerId: null,
      information: null
    }
    this.buttonClick = this.buttonClick.bind(this);
  }

  // 当新问题传入时,重置内部状态
  componentDidUpdate(prevProps) {
    if (prevProps.questionContent !== this.props.questionContent) {
      this.setState({
        selectedAnswerId: null,
        information: null
      });
    }
  }

  createButtons() {
    const { answers } = this.props.questionContent;
    const { selectedAnswerId } = this.state;
    
    return answers.map((element) => (
      <span 
        key={element._id} 
        onClick={() => this.buttonClick(element._id)} 
        className={`span-button-wrapper-25 ${element._id === selectedAnswerId ? "active" : ""}`}
      >
        <label>
          <span>{element.answer}</span>
        </label>
      </span>
    ));
  }

  buttonClick(id) {
    this.props.buttonClicked(id);
    // 从 props 的答案列表中找到对应提示信息
    const selectedAnswer = this.props.questionContent.answers.find(ans => ans._id === id);
    this.setState({
      selectedAnswerId: id,
      information: selectedAnswer?.information
    });
  }

  render() {
    const { question } = this.props.questionContent;
    const { information } = this.state;
    
    return (
      <div className="question-container">
        <div className="question-view">
          <div className="icon-row">
            <i className="fa fa-code" />
          </div>
          <div className="title-row">
            {question}
          </div>
          <div className="button-row">
            {this.createButtons()}
          </div>
          <div className="information-row">
            {ReactHtmlParser(information)}
          </div>
        </div>
      </div>
    );
  }
}

export default MultiChoice;

方案二:同步 props 到 state(不推荐)

如果一定要保留 state 中的 question 和 answerArray,需要在 componentDidUpdate 中监听 props 变化,手动更新 state:

componentDidUpdate(prevProps) {
  // 仅当 questionContent 变化时更新 state
  if (prevProps.questionContent !== this.props.questionContent) {
    this.setState({
      question: this.props.questionContent.question,
      answerArray: this.props.questionContent.answers,
      information: null
    });
  }
}

这种方式多了一层状态同步,容易引发不一致问题,所以优先选择方案一。


额外验证:Redux 部分是否正确

你的 Redux 代码是没问题的:

  • Reducer 每次返回新的对象(return { question: action.payload.data, selected: false }),符合 Redux 不可变更新的要求,能触发组件 props 更新。
  • App 组件的 mapStateToProps 正确映射了 state,所以 props 更新能传递到子组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:37:35