React冷门但很好用的知识点

介绍

最近在重读React官方文档,盘点一些不常用但有用的知识点。如果有啥说的不好的地方,欢迎指正!

推荐个翻译的不错的React文档

getSnapshotBeforeUpdate()

getSnapshotBeforeUpdate()为React生命周期函数, 在render()之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()

处理聊天滚动的示例:

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我们是否在 list 中添加新的 items ?
    // 捕获滚动位置以便我们稍后调整滚动位置。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
    // 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
    //(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

forceUpdate()

默认情况下,当组件的 stateprops 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。

调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。如果标记发生变化,React 仍将只更新 DOM。

简单来说forceUpdate()方法可以强制更新组件,所以不建议使用!

key

key顾名思义为组件的标识,当key改变时组件会重新注册!但我们使用最多的还是遍历!

const todos = [1, 2, 3, 4, 5];
const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

其实用index作为Key有问题,可以看这篇博客

状态提升

官方解释:通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到最近的共同父组件中去。

简单来说,就是两个子组件都使用父组件的一个参数,通过props把改参数传入子组件,并把改变该参数的方法一并传入子组件,通过调用该方法改变父组件共用的参数!

举个例子🌰

现在有ComponentA以及ComponentB,他们各有一个输入框,当我在其中一个输入框输入英文单词时,在另一个组件展示转换后的大小写。

class ComponentA extends React.Component {
  // 当input输入时,在另一个组件显示大的大小写转换
  handleChange(e) => {
    const { onChangeWordUpper } = this.props;
    onChangeWordUpper(e.target.value);
  };

  render() {
    const { word } = this.props;
    return (
      <h2>ComponentA enter: {word}</h2>
      <input onChange={this.handleChange} />
    );
  }
}
class ComponentB extends React.Component {
  // 当input输入时,在另一个组件显示大的大小写转换
  handleChange(e) => {
    const { onChangeWordLower } = this.props;
    onChangeWordLower(e.target.value);
  };

  render() {
    const { word } = this.props;
    return (
      <h2>ComponentB enter: {word}</h2>
      <input onChange={this.handleChange} />
    );
  }
}

父组件componentFather

class ComponentFather extends React.Component {
  state = {
    word: '';
  }

  // 转换为大写
  onChangeWordUpper(value) => {
    const word = value.toUpperCase()
    this.setState({ word });
  }
  
  // 转换为小写
  onChangeWordLower(value) => {
    const word = value.toLowerCase()()
    this.setState({ word });
  }

  render() {
    const { word } = this.state;
    const componentAProps = {
      word,
      onChangeWordUpper: this.onChangeWordUpper,
    };
    const componentBProps = {
      word,
      onChangeWordUpper: this.onChangeWordLower,
    };
    return (
      <ComponentA {...componentAProps} />
      <ComponentB {...componentBProps} />
    );
  }
}

未完待续

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章