hardfist/stackoverflow

使用key刷新非受控组件

hardfist opened this issue · 2 comments

之前实现编辑器的时候为了简化编辑器的状态管理使用了非受控组件,即props只负责编辑器的初始化,后续的状态都存放在编辑器内部,后来又加了支持草稿的需求,导致需要编辑器支持更新,对于非受控组件实现更新是个较为麻烦的事情,当时是通过componentWillReceiveProps来处理,如果传入的html发生变化,则刷新编辑器的内部状态(各种状态重置,比如输入框的focus状态,编辑状态,选择区的重置,draft内容json)

 componentWillReceiveProps(nextProps) {
    const {
      article
    } = this.props;
    const {
      article: nextArticle
    } = nextProps;

    if(article.html !== nextArticle.html) {
      this.refreshInternalState()
    }
  }

刷新状态的操作是个苦力活,尤其是编辑器内部进一步存在非受控组件的话,常常容易导致状态不一致。
现在回想起来,将整个组件销毁然后重建要简便的多,很幸运的是react官方推出了非受控组件的最佳实践,可以通过key来控制非受控组件的销毁和重建。如下所示 https://codesandbox.io/s/uncontrolled-state-em7y9

import React from "react";
import ReactDOM from "react-dom";
import { useState } from "react";

import "./styles.css";
class Editor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: this.props.defaultValue
    };
  }
  handleChange = e => {
    this.setState({
      value: e.target.value
    });
  };
  render() {
    return <input value={this.state.value} onChange={this.handleChange} />;
  }
}

function App() {
  const [value, updateValue] = useState(1);

  return (
    <div>
      <Editor defaultValue={value} key={value} />
      <button
        onClick={() => {
          updateValue(value + 1);
        }}
      >
        add
      </button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这样搞的话,原来组件内的状态不就没了嘛。

另外,用key来应对iframe的url更新问题,的确挺好用的。

这样搞的话,原来组件内的状态不就没了嘛。

另外,用key来应对iframe的url更新问题,的确挺好用的。

既然用key来做刷新了,意味着用key来映射组件内的状态,如果key刷新的话,意味着组件内的状态需要重建,如这里使用defaultValue来重建Editor的状态。