通过道具传递“这个”背景反模式?

时间:2016-11-04 12:17:20

标签: javascript reactjs

我有两个组件,父母和孩子,如下:

class Parent extends React.Component {
    shuffle() {
        ...
    }
    blur() {
        ...
    }
    next() {
        ...
    }
    previous() {
        ...
    }
    render() {
        return (
            <Child Parent={this} />
        );
    }
}

class Child extends React.Component {
    constructor(props) {
        super();

        this.state = {};

        this._onShuffleClick = this._onShuffleClick.bind(props.Parent);
        this._onPreviousClick = this._onPreviousClick.bind(props.Parent);
        this._onNextClick = this._onNextClick.bind(props.Parent);
    }
    _onShuffleClick(event) {
        event.preventDefault();

        this.shuffled ? this.shuffle(false) : this.shuffle(true); // I can call parents method here as the 'this' context is the 'Parent'.
        this.blur(event.target);
        this.setState({test "test"}); //I can set the parents state here
    }
    _onPreviousClick(event) {
        event.preventDefault();

        this.previous();
        this.blur(event.target);
    }
    _onNextClick(event) {
        event.preventDefault();

        this.next();
        this.blur(event.target);
    }
    render() {
        return (
            <a className="shuffle" key={1} onClick={this._shuffleOnClick}>{this.props.Parent.props.html.shuffle}</a>,
            <a className="previous" key={2} onClick={this._previousOnClick}>{this.props.Parent.props.html.previous}</a>,
            <a className="next" key={3} onClick={this._nextOnClick}>{this.props.Parent.props.html.next}</a>,
        );
    }
}

将上下文('this'关键字)作为反模式传递? 是否设置了孩子的父母状态不好?

如果我这样做,那么我就不必向孩子传递很多个人道具,我也可以设置孩子的父母的状态。

5 个答案:

答案 0 :(得分:2)

您可以与子组件中父级的state进行交互,但可能与您尝试实现此方式的方式不同。

如果您想将父母的所有props发送给孩子,您可以这样做:

<Child {...this.props} />

这样,您无需一次指定一个prop个人;相反,您只需将它们全部发送出去。请查看传播运营商 herehere以获取更多信息。有关MDN的更多信息:

  

扩展语法允许在需要多个参数(用于函数调用)或多个元素(用于数组文字)或多个变量(用于解构赋值)的地方扩展表达式。

如果您想要从孩子那里访问或修改父母的state,您必须稍微改变一下。通常,您将创建一个与父项中的state进行此交互的函数,然后将该函数作为prop发送给子项。像这样:

<强>父:

_modifyState = (bar) => {
  this.setState({foo: bar});
}
.....
<Child modifyState={this._modifyState} />

儿童:

this.props.modifyState("Hello world!");

以上内容会将父项中的state.foo设置为子组件中的字符串Hello world!

如果要访问所有state个变量,可以将其作为prop发送给子项(整个对象),然后使用一个函数(如上所述)修改整个状态(不只是一个属性) - 取决于你真正想要的东西。

答案 1 :(得分:1)

嗯,这主要是绕过道具的不好用法,你也可以选择{...props},我不想通过全名传递它,你也可以使用{{1} }。问题是,为什么你会提到父道具,这似乎是不好的做法,分而治之,只传递真正需要的道具,并且不要在你的孩子组件中假设某个父组件可用

当你传递事件处理程序时,让那些事件处理程序绑定到你当前的这个,但不要将它们绑定到一个预期的父项,就像这个例子

let { props } = this; let parentProps = props.Parent.props
var StyledButton = React.createClass({
  propTypes: {
  	clickHandler: React.PropTypes.func.Required,
    text: React.PropTypes.string.required
  },
  render: function() {
    let { clickHandler, text } = this.props;
    return <button type="button" onClick={clickHandler}>{text}</button>;
  }
});

var MyForm = React.createClass({
	click: function() {
  	alert('ouch');
  },
	render: function() {
  	return <fieldset>
    	<StyledButton clickHandler={this.click} text="Click me" />
    </fieldset>
  }
})

ReactDOM.render(
  <MyForm />,
  document.getElementById('container')
);

答案 2 :(得分:1)

是的,我认为你的代码是不好的做法。现在,您可以了解组件,了解使您的孩子不纯净的父组件。

当您的父实现更改时,子组件将因this.props.Parent.props.html.previous}而中断。

我认为每个react组件都应该通过调用props传递的parent函数来更新父组件。

class Parent extends React.Component {

    doSomethingBeacauseTheChildStateHasChanged() {
        // function
    }

    render() {
        <Child doSomething={doSomethingBeacauseTheChildStateHasChanged.bind(this)}/>
    }
}

class Child extends React.Component {

    render() {
        <button onClick={this.props.doSomething}>Child button</button>
    }

}

答案 3 :(得分:0)

注意:我不是专家和React初学者,将此视为意见而不是指南。

我认为是因为你迫使特定的实施。如果你想在GrandParent中使用这些方法,你会怎么做?如果你使用道具这个修改真的很容易,但是你的实现它会很痛苦。

还有一项名为PropTypes的功能。使组件可重用是非常棒的,但是如果你按照你的建议做的事情,那么你又不能使用它。

也许只是我,但这也造成了很大的混乱。你应该把你需要的一切都当成道具。

也像这样设置父状态

this.setState({test "test"}); //I can set the parents state here

对我来说似乎很糟糕。我宁愿从父作为prop传递一个函数,并在传递它之前绑定父类。

答案 4 :(得分:0)

您可以在Parent中触发一个功能。这是儿童与其父母沟通的正确方法。

class Parent extends React.Component {
  shuffle(e) {
    console.log(e.target);
    return false;
  }
  render() {
    return (
        <Child onShuffle={this.shuffle} />
    );
  }
}

class Child extends React.Component {
  render() {
    return(
      <a href='#' onClick={this.props.onShuffle}>Shuffle</a>
    );
  }
}
Child.propTypes = {
  onShuffle: React.PropTypes.func
}