【问题标题】:Make sure a new instance of certain component is used确保使用某个组件的新实例
【发布时间】:2016-09-19 10:02:03
【问题描述】:

我觉得这是一个“错误”的问题,但无论如何:

我正在制作某种测验应用程序(使用 redux 进行状态管理)。 (此处显示重要部分)

quiz.js

<Slider {...sliderSettings} slideIndex={currentQuestionIndex}>
    <Start onStart={() => onNextQuestion()} topicId={topicId}  />

    {
        questions.map((question, ndx) => {
            return (
                <Question {...question} done={onDone} key={`question-${question.id}`} />
            );
        })
    }

    <Result score={score} onRestart={() => onRestart()}/>
</Slider>

question.js

<div className="question">
    <h2 className="question__text">{ question }</h2>
    <MultipleChoice options={answers} onChange={done} />
</div>

多项选择.js

const
    initialState = {
        selectedValue: null
    };

class MultipleChoice extends Component {
    constructor(props) {
        super(props);
        this.state = initialState;
    }

    handleChange(value, correct) {
        this.setState({
            selectedValue: value
        });

        this.props.onChange(correct);
    }

    render() {
        const
            { options } = this.props,
            getStateClass = (option, ndx) => {
                let sc = '';

                if (this.state.selectedValue !== null) {
                    if (this.state.selectedValue === ndx) {
                        sc = option.correct ? 'is-correct' : 'is-incorrect';
                    } else if (option.correct) {
                        sc = 'is-correct';
                    }
                }

                return sc;
            };

        return (
            <ul className="multiple-choice">
                { options.map((option, ndx) => {
                    return (
                        <li key={`option-${ndx}`} className={cx('multiple-choice__option', getStateClass(option, ndx))}>
                            <button className="multiple-choice__button" onClick={() => this.handleChange(ndx, option.correct)}>{option.answer}</button>
                        </li>
                    );
                }) }
            </ul>
        );
    };
}

export default MultipleChoice;

问题在于 MultipleChoice 的呈现。它使用内部状态来显示哪个答案是错误的和正确的。

在 quiz.js 中,onRestart 调度一个 redux 操作,它更新 store 以获取一些新问题并将 currentQuestionIndex 重置为 0。这一切都有效。 但不知何故,有时 MultipleChoice 元素被“重用”并且仍然显示它在上一轮问题中的状态。换句话说,大多数情况下会安装一个新的 MultipleChoice,但有时不会。这是反应和解,如果我理解正确的话?

但是我该如何解决这个问题呢?在我看来,MultipleChoice 需要它的内部状态。那么我应该以某种方式重置此状态吗?或者确保每次都安装一个新的 MultipleChoice?还是我在这里问错了问题?

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    我查看了your repository,问题是noted in another answer 正确的是您的&lt;Question&gt;(以及内部&lt;MultipleChoice&gt;)组件从不卸载,因此它们保持其状态。

    通常这在 React 中不会经常出现,因为人们通常希望在组件位于树中时保留状态。当不再需要状态时,人们通常会停止在 render() 方法中包含组件,并且 React 会卸载它们。下次渲染它们时,它们的状态会被重置。

    在您的示例中,状态不会重置,因为您始终保持&lt;Question&gt;s 可见,即使在测验运行之间也是如此。您可以看到&lt;Question&gt;s 在我们开始测验之前已经挂载,并在结束后保持挂载:

    那么我们怎样才能强制 React 重置它们的状态呢?共有三个选项:

    • 您可能会导致它们卸载。下次他们上马时,他们将拥有一个新的状态。这通常是最简单的解决方案,因为您实际上并没有在初始“开始测验”页面上显示问题。例如,您可以在&lt;Questions&gt;render() 方法中,在渲染questions.map(...) 之前添加currentQuestionIndex &gt; 0 &amp;&amp; 保护。

    • 您可以将新的keys 传递给与之前的keys 不匹配的他们。您目前正在使用question-${question.id} 作为key,但即使您重试测验,也会为同一问题生成相同的密钥。为了解决这个问题,您可以引入一个新的状态变量(在 Redux 中或在顶级组件状态中),例如,quizAttemptIndex,并在任何新尝试时增加它。然后您可以将密钥更改为question-${quizAttemptIndex}-${question.id}。这样,再次尝试测验将重置问题的内部状态(并使其重新加载)。

    • 1234563然后,在它里面,如果nextProps.quizAttemptIndex !== this.props.quizAttemptIndex,你可以在componentWillReceiveProps(nextProps)里面this.setState({ selectedValue: null })

    您可以选择任一解决方案,具体取决于始终保持问题的重要性。

    【讨论】:

      【解决方案2】:

      据我了解,您希望您的 MultipleChoice 组件在您希望它这样做时刷新其状态。但是当您在组件中使用反应状态时,只要您的组件没有卸载,您的 MultipleChoice 中的反应状态就会保持其最新状态。

      这种行为是反应状态所期望的,因为大多数情况下你想将它用于内部行为。当某个按钮或某些东西触发您的组件这样做时,也许您想在组件中切换一些 ui 数据。或者你想控制你的输入表单等。

      但是你期望的应该在 redux 状态下完成。您的组件应该是可重用的,它不关心它的安装位置。您可以使用来自 redux 的 props 将与挂载位置相关的数据传递给 MultipleChoice。所以现在你有了一个可重用的组件。不要花太多时间安装等。您可以查看 github 上的 react-redux 存储库以熟悉如何塑造项目的数据流。何时使用 redux state 通过反应状态来做出决定或处理组件中的状态。

      【讨论】:

      • 我认为你理解正确。我已经想到了您提出的解决方案,但这对我来说感觉很奇怪。我现在的感觉是:“如果这不是内部状态的情况,那是什么?”
      猜你喜欢
      • 2019-03-16
      • 1970-01-01
      • 2017-06-28
      • 1970-01-01
      • 2013-03-23
      • 2018-11-16
      • 2021-01-16
      • 1970-01-01
      • 2018-11-26
      相关资源
      最近更新 更多