reactjs中的反模式究竟是什么?

时间:2018-06-03 16:18:17

标签: javascript reactjs

假设我有一个父组件。

Parent.js

class Parent extends React.Component {

  someMethod () {
    LoadDataforChild();
  }

  render() {

    return (
      <div>
        <Child someMethod={this.someMethod}/>
      </div>
    );
  }
}

export default Parent;

Child.js(儿童是纯粹的组成部分)

class Child extends React.Component {

  componentWillMount() {
    this.props.someMethod();
  }

  render() {
    return (
      <div>
        Hello child
      </div>
    );
  }
}

我完全没有意识到反应中的反模式。我在Child(纯组件)中调用了父方法。这是反模式吗?什么是父母和儿童组成部分的反模式究竟是什么?

2 个答案:

答案 0 :(得分:1)

一般来说反模式并不多,因为在父母中有数据获取的确定用例 - 想想多个孩子等等。但通常这是通过回调来完成的,例如当用户点击按钮时比在山上。

在您的示例中,将数据作为prop直接传递给子级并处理父级mount事件中的数据加载会更有意义。

注意,您应该避免使用componentWillMount(),因为这是一种反模式。请改用componentDidMount()Read here

答案 1 :(得分:1)

将您的问题扩展到reactjs中的反模式,我想广泛回答,因为我可以基于off.docs,文章和我自己的经验:

  • 不要以组件状态或商店(例如redux商店)存储组件
    //REDUX REDUCER
    const initialState = {
        isHOCOpened: false,
        child: null
      }

    export default reducer = (state = initialState, {type, content}) => {
        switch (type) {
          case ('openHOC'): {
            const updatedState = {...state};
            updatedState.isHOCOpened = true;
            updatedState.child = content;
            return {
              ...state, ...updatedState
            }
        ...
    }

    //PARENT COMPONENT
    ...some other imports;
    import  ChildElement from './ChildElement';
    export default class ParentElement extends Component {
      ...some code...
      render() {
        const { openHOC, HOCcontent } = this.props;
        return (
          <div onClick={()=>this.openHOC(<ChildElements/>)}>
            <HOCElement/>
          </div>
    }

    //HIGHER ORDER COMPONENT
    export default const HOC = ({isHOCOpened, child}) => {
      ...some code...
      return (
        <div>
          {isOpened && {children}}
        </div>
      )
    }

推荐的方式是

    ...some other imports;
    import  ChildElement from './ChildElement';
    export default class ParentElement extends Component {
      state = {
        isHOCOpened: false,
      }

      openHOC = () => this.setState({openHOC: true});

      render() {
        return (
          <div onClick={this.openHOC}>
            {isOpened && <HOCElement/><ChildElement/></HOCElement>}
          </div>
      }
    }

    ...
    export default const HOC = ({children}) => {
      ...some stuff...
      return (
        <div>{children}</div>
      )

整理应用逻辑,避免在状态/存储中存储组件;

  • 不要在事件中直接传递setState
    onClick={() => {
      //some code
      this.setState({isOpened: true})
    }

更好地利用事件,并将其仅存储为之前的示例:

      openHOC = () => {
        //some code
        return this.setState({openHOC: true})
      };

      render() {
        return (
          <div onClick={this.openHOC}>
            {isOpened && <HOCElement/><ChildElement/></HOCElement>}
          </div>
      }

它会影响性能,因为它每次都会创建函数,但这仅对ReactJS产生了对JS的全面理解。请查看该文章,以更深入地讨论this

  • 在每次传递props变量时都不要绑定,如果您将其链接到要执行该变量的环境:
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          name: ''
        };
      }

      updateValue(evt) {
        this.setState({
          name: evt.target.value
        });
      }

   render() {
    return (
      <form>
        <input onChange={this.updateValue.bind(this)} value={this.state.name} />    
      </form>
    )
      }
    }

而是在构造函数中绑定所有变量:

    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          name: ''
        };
        this.updateValue = this.updateValue.bind(this);
    }
  • 请勿将索引用作键道具
    <ul>
      {liArray.map( (e,i) => <li key={i}>{e.text}</li>}
    </ul>

这不是完全反模式,而是简单的错误代码和意外结果。由于在off docs中已经写了很多次,因此React使用Keys来跟踪DOM树中的更改并重绘它,因此尽管索引是对其数组位置的更改,但Keys必须是唯一的; 将独特的道具作为ID或其他{liArray.map(e => <li key={e.id}>{e.text}</li>}

  • 另外一个反模式不能直接在setState中计算值setState({value: this.state.counter + passedValue}) 在调用setState之前执行以下操作:
    updateValue(passedValue) {
       const result = this.state.counter + passedValue;
       setState({value: result})
    }
  • 不要在setState后面传递函数,希望在setState之后立即执行该函数:
      updateValue(value) {
        this.setState({counter: value});
        this.addToCounter(1)
      }

因为setState是异步的check it 将其作为setState中的第二个参数传递,以使其在组件为新状态时运行:

      updateValue(value) {
        this.setState(
          {counter: value},
          ()=>this.addToCounter(1)
        )
      }
  • 和最后一个不使用小写字母命名组件。 React足够聪明:)识别出想要传递html标签或react组件: 这将不起作用:<mycomponent>content</mycomponent>,但这可以解决问题<Mycomponent>content</MyComponent> Button button ;