简体   繁体   English

通过道具传递“此”上下文是否是反模式?

[英]Is passing the “this” context through props an anti-pattern?

I have two components, a parent and a child like so: 我有两个部分,像这样的父母和孩子:

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>,
        );
    }
}

Is passing the context ('this' keyword) as a prop an anti-pattern? 将上下文(“ this”关键字)作为道具传递是反模式吗? Is setting the state of the parent from the child bad? 从孩子设置父母的状态是否不好?

If I do this I then don't have to pass a lot of individual props to the child and I can also set the state of the parent from the child. 如果这样做,则不必将很多单独的道具传递给孩子,而且我还可以从孩子那里设置父母的状态。

You can interact with the state of a parent from a child-component, but probably not the way you are trying to achieve this. 您可以通过子组件与父组件的state进行交互,但可能无法达到此目的。

If you want to send in all props of the parent down to a child, you can do: 如果要将父级的所有props发送给孩子,则可以执行以下操作:

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

This way, you don't need to specify each individual prop one at a time; 这样,您无需一次指定每个prop instead, you just send them all in. Check out the spread operator here and here for more info. 相反,您只需将它们全部发送出去即可。 在此处此处查看价差运算符以获取更多信息。 More info also on MDN: 有关MDN的更多信息:

The spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected. 扩展语法允许在需要多个参数(用于函数调用)或多个元素(用于数组文字)或多个变量(用于解构赋值)的地方扩展表达式。


If you want to access or modify the state of a parent from a child you have to do this slightly differently. 如果要访问或修改孩子的父母state ,则必须稍有不同。 Typically, you would create a function that does this interaction with the state in your parent and then send that function as a prop down to the child. 通常,您将创建一个函数来与父代中的state进行此交互,然后将该函数作为prop发送给子代。 Like this: 像这样:

Parent: 家长:

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

Child: 儿童:

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

The above will set state.foo in the parent to the string Hello world! 上面将在父级中将state.foo设置为字符串Hello world! from the child component. 来自子组件。

If you want access to all state variables, you could send it in as a prop to the child (the whole object) and then have a function (like above) which modifies the entire state (not just one property) - depends what you want really. 如果要访问所有state变量,则可以将其作为prop发送给孩子(整个对象),然后有一个函数(如上)修改整个状态(而不仅仅是一个属性)-取决于您想要的真。

Well, it's mainly a bad usage of passing around the props, you could also go for {...props} instead, and I wouldn't want to pass it through the full name, you can also use let { props } = this; let parentProps = props.Parent.props 好吧,这主要是传递道具的一种不好用法,您也可以使用{...props} ,而我也不想通过全名传递它,也可以使用let { props } = this; let parentProps = props.Parent.props let { props } = this; let parentProps = props.Parent.props . let { props } = this; let parentProps = props.Parent.props The question is also, why would you refer to parent props, that seems the bad practise, divide and conquor, only pass the props that are really needed, and do not assume in your child components that a certain parent component is available 问题还在于,为什么您要引用父项道具,看来这是不好的做法,划分和征服,只能通过真正需要的道具,而不会在子组件中假设某个父项组件可用

When you pass event handlers down, let those eventhandlers be bound to your current this, but don't bind them in the child to an expected parent, a bit like this example 当您向下传递事件处理程序时,让这些事件处理程序绑定到当前的事件处理程序,但不要将其在子级中绑定到预期的父级,这有点像此示例

 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') ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"> <!-- This element's contents will be replaced with your component. --> </div> 

Yes I do think your code is bad practice. 是的,我确实认为您的代码是错误的做法。 Now you chid components know about the parent component which makes your child impure. 现在,您可以让组件知道有关使孩子不纯的父组件的信息。

When your parent implementation changes, the child components will break because of this.props.Parent.props.html.previous} . 当您的父实现更改时,子组件会因为this.props.Parent.props.html.previous}this.props.Parent.props.html.previous}

I think each react component should update the parent by calling the parents functions passed by the props. 我认为每个react组件都应该通过调用道具传递的parent函数来更新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>
    }

} }

Note: I am not an expert and React beginner, treat this as an opinion rather than guideline. 注意:我不是专家,也不是React初学者,请将其视为观点而非指导。

I think yes cause you force particular implementation. 我认为是的,因为您强制执行特定的操作。 What would you do if you wanted to have those methods in GrandParent? 如果想在GrandParent中使用这些方法,该怎么办? If you use props this modification is really easy, but with your implementation it would be pain in the ass. 如果您使用道具,那么这种修改确实很容易,但是在您的实现中,这样做很麻烦。

There is also a feature called PropTypes . 还有一个称为PropTypes的功能。 It's really great to make components reusable, but it's yet another thing you can't use if you do the things like you have proposed. 使组件可重用确实很棒,但是如果您像建议的那样做,那是您不能使用的另一件事。

Maybe it is just me but this also creates a great confusion. 也许只有我一个人,但这也造成了极大的困惑。 You should pass everything you need as props. 您应该通过所有需要的道具。

Also setting parent state like this 也像这样设置父状态

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

seems bad to me. 对我来说似乎很糟糕。 I would rather pass a function from parent as a prop and bind parent before passing it down. 我宁愿从父级传递一个函数作为道具,并在向下传递之前绑定父级。

You can trigger a function in the Parent. 您可以在父级中触发功能。 This is the correct way to a children communicates with its 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM