当第一个

时间:2018-04-06 04:29:43

标签: reactjs typescript

我写了一个简单的React POC,其中有一个Main组件和两个子组件。应用程序的整个状态保留在Main组件中。当状态改变时,当新状态作为props传递时,子组件将被重新呈现。

import * as React from 'react'
import * as ReactDOM from 'react-dom'
class Comp1 extends React.Component<IProps1, any> {
  render() {
    console.log('going to render Component1')
    return (
      <React.Fragment>
        <input type='text' value={this.props.curtext} onChange={(e) => this.props.handleChange(e.target.value)} />
        <button onClick={(e) => this.props.onSave(this.props.curtext)}>save</button>
      </React.Fragment> 
    )
  }
}
class Comp2 extends React.Component<IProps2, any> {
  render() {
    console.log('going to render Component2')
    return (
      <React.Fragment>
        <ul>
          {this.props.items.map((item, index) => <li key={index}>{item}</li>)}
        </ul>
      </React.Fragment>
    )
  }
}
class Main extends React.Component<any, IState> {
  constructor(props: any) {
    super(props)
    this.state = {
      currtext: "",
      items: []
    }
    this.handleChange = this.handleChange.bind(this)
    this.onSave = this.onSave.bind(this)
  }
  handleChange(text: string) {
    this.setState({currtext: text})
  }
  onSave(text: string) {
    var copy = this.state.items;
    copy.push(text)
    this.setState({currtext: "", items: copy})
  }
  render() {
    return (
      <React.Fragment>
        <Comp1 handleChange={this.handleChange} curtext={this.state.currtext} onSave={this.onSave} />
        <Comp2 items= {this.state.items} />
      </React.Fragment>
    )
  }
}

ReactDOM.render(<Main />, document.getElementById("root"))

interface IState {
  currtext: string
  items: Array<string>
}
interface IProps1 {
  handleChange: (text: string) => void,
  curtext: string,
  onSave: (text: string) => void
}

interface IProps2 {
  items: Array<string>
}

该应用程序的唯一问题是当属性&#34; currtext&#34;状态更改,Component2仍然重新呈现。

我期望的是curtext更改,然后呈现Component1,当项目更改时,Component2重新呈现。

但是现在我看到Component2在输入文本框中的每次击键时都被重新渲染,这只会改变Component2不关心的部分状态。

编辑::根据以下建议,我将组件2的代码更改为

class Comp2 extends React.Component<IProps2, any> {
  shouldComponentUpdate(nextProps: IProps2, nextState: any) {
    console.log(nextProps.items);
    console.log(this.props.items);
    if (nextProps.items.toString() === this.props.items.toString()) {
      return false 
    } else { 
      return true
    }
  }
  render() {
    console.log('going to render Component2')
    return (
      <React.Fragment>
        <ul>
          {this.props.items.map((item, index) => <li key={index}>{item}</li>)}
        </ul>
      </React.Fragment>
    )
  }
}

现在,如果我在文本框中输入内容并单击“保存”。我看到nextProps.items和this.props.items总是相同的,因此我的component2根本不会渲染。

1 个答案:

答案 0 :(得分:1)

Comp2重新渲染的原因是因为父状态改变了父级渲染方法内的所有内容将被重新渲染。

 class Comp2 extends React.Component<IProps2, any> {
  shouldComponentUpdate(nextProps, nextState) {
  if(nextProps.currtext) return false;
  return true;
  }
  render() {
    console.log('going to render Component2')
    return (
      <React.Fragment>
        <ul>
          {this.props.items.map((item, index) => <li key={index}>{item}</li>)}
        </ul>
      </React.Fragment>
    )
  }
}

尝试添加shouldComponentUpdate生命周期挂钩。

将currtext作为道具传递给Comp2。如果currtext包含字母,Comp2将不会更新。一旦你提交和currtext成为&#34;&#34;空它会更新。

<Comp2 items= {this.state.items} currtext={this.state.currtext} />

也不要直接改变状态。

  onSave(text: string) {
    var copy = this.state.items.slice();
    copy.push(text)
    this.setState({currtext: "", items: copy})
  }