简体   繁体   English

对更改数据的智能/哑组件模式做出反应

[英]react smart/dumb component pattern for changing data

I'm starting to implement the smart/dumb component pattern where the "dumb" component knows nothing about it's environment and receives all of it's data through props. 我开始实现智能/哑巴组件模式,其中“哑巴”组件对其环境一无所知,并通过道具接收其所有数据。 What do you do when the dumb component has to submit or change data? 当哑部件必须提交或更改数据时,您该怎么办? How can it communicate with the outside world and still be "dumb"? 它如何与外界交流并仍然是“哑巴”?

Here's my basic example I'm using to figure this pattern out. 这是我用来弄清楚这种模式的基本示例。 If I were to add and onClick event to the MyTask component that updated a counter in the DB, what would handle that event? 如果要向MyTask组件添加onClick事件并更新数据库中的计数器,那么该事件将如何处理?

// components/MyList.jsx

import React from 'react';

export default class MyList extends React.Component {
    render() {
        return(
            <div>
                <h3>{this.props.listName}</h3>
                <ul>
                    {this.props.tasks.map((task) => (
                        <MyTask key={task.id} task={task} />
                    ))}
                </ul>
            </div>
        );
    }
}
MyList.propTypes = {
    listName: React.PropTypes.string.isRequired,
    tasks: React.PropTypes.array.isRequired,
}



export class MyTask extends React.Component {
    render() {
        return (
            <li>{this.props.task.text}</li>
        );
    }
}
MyTask.propTypes = {
    task: React.PropTypes.object.isRequired,
}

and the app: 和应用程序:

// app.jsx

import React from 'react';
import MyList from './components/MyList.jsx'


export class TaskApp extends React.Component {

    getList() {
        return('Today Stuff');
    }

    getTasks() {
        return([
            {id: 1, text: 'foo'},
            {id: 2, text: 'diggity'},
            {id: 3, text: 'boo'},
            {id: 4, text: 'bop'}
        ]);
    }

    render() {
        return (
            <MyList listName={this.getList()} tasks={this.getTasks()} />
        );
    }
}

Generally speaking you can handle this by passing function references from your 'smart' components down to your 'dumb' components. 一般而言,您可以通过将功能引用从“智能”组件传递到“哑”组件来处理此问题。 The dumb component then isn't responsible for implementing any of the logic associated with the function, just telling the smart component 'I've been clicked'. 然后,哑组件不负责实现与该功能关联的任何逻辑,只是告诉智能组件“我已被点击”。

In this case inside of your TaskApp class in app.jsx you could have your click handler: 在这种情况下,您可以在app.jsx的TaskApp类内部拥有单击处理程序:

//app.jsx
...
handleClick() {
  // Update the DB counter by 1
}
...
render () {}

Then pass handleClick through your components as a prop: 然后将handleClick作为道具传递给您的组件:

<MyList listName={this.getList()} tasks={this.getTasks()} handleClick={this.handleClick} />

<MyTask key={task.id} task={task} handleClick={this.props.handleClick} />

And execute it in the MyTask component when a list element is clicked: 并在单击列表元素时在MyTask组件中执行它:

<li onClick={this.props.handleClick}>{this.props.task.text}</li>

Keep in mind that if the handleClick() function is making use of 'this' at all, you'll need to .bind(this) on your function reference when you pass it down (or bind it in the constructor / use ES6 fat arrow functions). 请记住,如果handleClick()函数完全使用了“ this”,则在传递给函数引用时,您需要在函数引用上使用.bind(this)(或将其绑定到构造函数中/使用ES6 fat箭头功能)。

EDIT : For examples of the other ways to bind 'this', you could in the constructor of your class assign the bound function to your this.handleClick reference, so: 编辑 :对于其他绑定方式'this'的示例,您可以在类的构造函数中将绑定函数分配给this.handleClick引用,因此:

export default class TaskApp extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

...
...
}

Which allows you to use this.handleClick the way you would normally expect. 它允许您以通常期望的方式使用this.handleClick。

Or you could use ES6 fat arrow functions, which preserve the context of 'this' when they are called: 或者,您可以使用ES6粗箭头功能,这些功能在被调用时保留“ this”的上下文:

<MyList 
  listName={this.getList()} 
  tasks={this.getTasks()} 
  handleClick={() => this.handleClick} />

Assuming that TaskApp is the smart component and MyList is the dumb component, it should be something like 假设TaskApp是智能组件,而MyList是愚蠢的组件,则它应该类似于

Smart Component 智能组件

// app.jsx

import React from 'react';
import MyList from './components/MyList.jsx'


export class TaskApp extends React.Component {

    getList() {
        return('Today Stuff');
    }

    getTasks() {
        return([
            {id: 1, text: 'foo'},
            {id: 2, text: 'diggity'},
            {id: 3, text: 'boo'},
            {id: 4, text: 'bop'}
        ]);
    }
    handleClick(task){
      // update the db here
    }

    render() {
        return (
            <MyList listName={this.getList()} tasks={this.getTasks()} 
                onClick={this.handleClick}/>
        );
    }
}

Dumb Component 哑成分

// components/MyList.jsx

import React from 'react';

export default class MyList extends React.Component {
    render() {
        return(
            <div>
                <h3>{this.props.listName}</h3>
                <ul>
                    {this.props.tasks.map((task) => (
                        <MyTask onClick={() => this.props.onClick(task)}
                             key={task.id} task={task} />
                    ))}
                </ul>
            </div>
        );
    }
}
MyList.propTypes = {
    listName: React.PropTypes.string.isRequired,
    tasks: React.PropTypes.array.isRequired,
}



export class MyTask extends React.Component {
    render() {
        return (
            <li onClick={this.props.onClick}>{this.props.task.text}</li>
        );
    }
}
MyTask.propTypes = {
    task: React.PropTypes.object.isRequired,
}

You can pass the event handler callback as a prop to MyTask : 您可以将事件处理程序回调作为道具传递给MyTask

<MyTask onClick={this.handleTaskClick.bind(this)} ... />

And then use it in MyTask: 然后在MyTask中使用它:

<li onClick={this.props.onClick}>...</li>

See: https://facebook.github.io/react/docs/tutorial.html#callbacks-as-props 参见: https : //facebook.github.io/react/docs/tutorial.html#callbacks-as-props

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

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