避免在 react js 中从“输入”或“文本区域”不断重新渲染

IT技术 reactjs
2021-05-16 11:48:00

目前在 react js 中,当我想绑定文本区域或带有“状态”的输入时,每次用户输入单个字母时,我都需要设置 onChange 方法和 setState()

我听说如果你 setState react js 刷新并重新渲染此组件中的所有内容

有没有更有效的方法来做到这一点?在这种情况下使用“shouldComponentUpdate”将是不正确的,因为如果我不进行“状态”更新,所有用户输入都会被卡住..

4个回答

嗯,这就是你在 React 中实现受控输入元素的方式。

但是,如果性能是您的主要关注点,您可以将输入元素隔离在一个单独的有状态组件中,因此只会触发自身的重新渲染,而不是整个应用程序的重新渲染。

所以像:

class App extends Component {    
  render() {
    return (
      <div>
        ...
        <MyInput />
        ...
      </div>
    );
  }
}


class MyInput extends Component {
  constructor() {
    super();
    this.state = {value: ""};
  }

  update = (e) => {
    this.setState({value: e.target.value});
  }

  render() {
    return (
      <input onChange={this.update} value={this.state.value} />
    );
  }
}

或者,您可以只使用不受控制的输入元素。例如:

class App extends Component {    
  render() {
    return (
      <div>
        ...
        <input defaultValue="" />
        ...
      </div>
    );
  }
}

但是,请注意,通常建议使用受控输入。

正如@Chris 所说,您应该创建另一个组件来优化仅对指定组件的重新渲染。

但是,在某些用例中,您需要更新父组件或使用输入中输入的值将操作分派给您的一个减速器。

例如,我创建了一个 SearchInput 组件,它为输入中输入的每个字符更新自身,但当至少有 3 个字符时才调用该onChange函数

注意:当用户停止输入至少 200 毫秒时才clearTimeout调用该onChange函数很有用

import React from 'react';

class SearchInput extends React.Component {
  constructor(props) {
    super(props);
    this.tabTimeoutId = [];
    this.state = {
      value: this.props.value,
    };

    this.onChangeSearch = this.onChangeSearch.bind(this);
  }

  componentWillUpdate() {
    // If the timoutId exists, it means a timeout is being launch
    if (this.tabTimeoutId.length > 1) {
      clearTimeout(this.tabTimeoutId[this.tabTimeoutId.length - 2]);
    }
  }

  onChangeSearch(event) {
    const { value } = event.target;

    this.setState({
      value,
    });

    const timeoutId = setTimeout(() => {
      value.length >= this.props.minSearchLength ? this.props.onChange(value) : this.props.resetSearch();
      this.tabTimeoutId = [];
    }, this.props.searchDelay);

    this.tabTimeoutId.push(timeoutId);
  }

  render() {
    const {
      onChange,
      minSearchLength,
      searchDelay,
      ...otherProps,
    } = this.props;

    return <input
      {...otherProps}
      value={this.state.value}
      onChange={event => this.onChangeSearch(event)}
    />
  }
}

SearchInput.propTypes = {
  minSearchLength: React.PropTypes.number,
  searchDelay: React.PropTypes.number,
};
SearchInput.defaultProps = {
  minSearchLength: 3,
  searchDelay: 200,
};

export default SearchInput;

希望能帮助到你。

您需要像代码片段一样在构造函数中绑定 onChange() 事件函数:

class MyComponent extends Component {
  constructor() {
    super();
    this.state = {value: ""};
    this.onChange = this.onChange.bind(this)
  }

  onChange= (e)=>{
    const formthis = this;
    let {name, value} = e.target;

    formthis.setState({
      [name]: value
    });
  }

  render() {
    return (
      <div>
        <form>
            <input type="text" name="name" onChange={this.onChange}  />
            <input type="text" name="email" onChange={this.onChange}  />
            <input type="text" name="phone" onChange={this.onChange}  />
            <input type="submit" name="submit" value="Submit"  />
        </form>
      </div>
    );
  }
}

你不需要一个复杂的react解决方案来解决这个问题,只需要一些关于何时更新状态的常识。实现此目的的最佳方法是setState在超时内封装您的调用。

class Element extends React.Component {
    onChange = (e) => {
        clearTimeout(this.setStateTimeout)
        this.setStateTimeout = setTimeout(()=> {
            this.setState({inputValue: e.target.value})
        }, 500)
    }
}

这只会在最后一次击键后 500 毫秒后在您的react元素上设置状态,并防止在您的用户键入时重新渲染元素。