React中的状态和道具有什么区别?

我正在观看React的Pluralsight课程,导师说道具不应该改变。 我现在正在阅读一篇关于道具和状态的文章(uberVU / react-guide) ,它说

道具和状态更改都会触发渲染更新。

后来在文章中说:

道具(属性的简称)是一个组件的configuration,如果你愿意,它的选项。 他们从上面收到而且是不变的。

  • 所以道具可以改变,但是它们应该是不变的?
  • 什么时候应该使用道具,什么时候使用状态?
  • 如果你有React组件需要的数据,是否应该通过道具或通过getInitialState在React组件中设置?

道具和状态是相关的。 一个组件的状态通常会成为子组件的道具。 Props作为React.createElement()的第二个parameter passing给父级的render方法内的子React.createElement() ,如果使用的是JSX,那么就是更熟悉的标签属性。

 <MyChild name={this.state.childsName} /> 

childsName的父状态值成为孩子的this.props.name 。 从孩子的angular度来看,名字道具是不变的。 如果需要改变,父母应该改变其内部状态:

 this.setState({ childsName: 'New name' }); 

React会把它传播给你的孩子。 一个自然而然的后续问题是:如果孩子需要改变自己的名字,该怎么办? 这通常通过子事件和父callback完成。 孩子可能会暴露一个名为onNameChanged的事件。 父母然后通过传递callback处理程序来订阅事件。

 <MyChild name={this.state.childsName} onNameChanged={this.handleName} /> 

孩子会通过调用例如this.props.onNameChanged('New name')将其请求的新名称作为parameter passing给事件callback,并且父母将使用事件处理程序中的名称来更新其状态。

 handleName: function(newName) { this.setState({ childsName: newName }); } 

为了亲子沟通,只需通过道具。

使用状态在您的控制器视图中存储您当前页面所需的数据。

使用道具将数据和事件处理程序传递给您的子组件。

在处理组件中的数据时,这些列表应该有助于指导您。

道具

  • 不可变的(让我们做快速的参考检查)
  • 用于从您的视图控制器(您的顶级组件)向下传递数据
  • 更好的性能,使用它将数据传递给子组件

  • 应该在您的视图控制器(您的顶级组件)中进行pipe理,
  • 易变的
  • 糟糕的performance
  • 不要从子组件访问它,而是用道具传递它

对于没有父子关系的两个组件之间的通信,可以设置自己的全局事件系统。 订阅componentDidMount()中的事件,取消订阅componentWillUnmount(),并在收到事件时调用setState()。 stream量模式是可能的安排方式之一。 – https://facebook.github.io/react/tips/communicate-between-components.html

什么组件应具有状态?

你的大多数组件应该只是从道具上获取一些数据并进行渲染。 但是,有时您需要响应用户input,服务器请求或时间的推移。 为此,你使用状态。

尽量保持尽可能多的组件无状态 。 通过这样做,您可以将状态隔离为最合乎逻辑的位置,并将冗余最小化,从而更容易推断您的应用程序。

一个常见的模式是创build几个无状态的组件,它们只是呈现数据,并且在层次结构中有一个有状态的组件,通过道具将其状态传递给子组件。 有状态的组件封装了所有的交互逻辑,而无状态的组件负责以声明的方式呈现数据。 – https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-c​​omponents-should-have-state

什么应该在国家?

状态应包含组件的事件处理程序可能更改以触发UI更新的数据。 在真正的应用程序中,这些数据往往非常小,并且可以JSON序列化。 在构build有状态组件时,请考虑其状态的最小可能表示forms,并仅将这些属性存储在this.state中。 render()内部根据这个状态简单地计算你需要的任何其他信息。 你会发现,以这种方式思考和编写应用程序往往会导致最正确的应用程序,因为向状态添加冗余或计算值意味着您需要明确地保持它们同步,而不是依靠React为您计算它们。 – https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#what-should-go-in-state

我最喜欢的道具vs状态总结在这里: https : //github.com/uberVU/react-guide/blob/master/props-vs-state.md大帽子给那些家伙提示。 以下是该页面的修改版本:


道具vs状态

tl; dr如果某个组件需要在某个时间点更改其某个属性,则该属性应该是其状态的一部分,否则应该只是该组件的支柱。


道具

道具(属性的简称)是一个组件的configuration。 它们是从上面收到的,并且就接收它们的组件而言是不变的。 一个组件不能改变它的道具,但是它负责把它的子组件的道具放在一起。 道具不一定只是数据 – callback函数可以作为道具传入。

状态是一个数据结构,当一个组件安装时以默认值开始。 它可能随着时间而变化,主要是由于用户事件。

组件在内部pipe理自己的状态。 除了设置初始状态之外,没有任何业务摆弄子女的状态。 您可能将状态概念化为该组件的私有状态。

改变道具和状态

                                                   道具状态
    可以从父组件获得初始值? 是的是的
    可以通过父组件更改? 是的
    可以在组件内设置默认值吗?是的
    可以改变里面的组件? 不,是的
    可以为子组件设置初始值? 是的是的
    可以更改在子组件? 是的
  • 请注意,从父母接收到的道具和状态初始值都将覆盖在组件内定义的默认值。

这个组件是否有状态?

状态是可选的。 由于状态增加了复杂性并降低了可预测性,所以没有状态的组件是可取的 即使你在交互式应用程序中显然不能没有状态,也应该避免拥有太多有状态的组件。

组件types

无状态组件只有道具,没有状态。 除了render()函数之外,没有太多的事情要做。 他们的逻辑围绕着他们收到的道具。 这使得他们很容易跟踪,并进行testing。

状态组件道具和状态。 当你的组件必须保持某种状态时才使用它们。 这是客户端 – 服务器通信(XHR,networking套接字等),处理数据和响应用户事件的好地方。 这些物stream应该封装在中等数量的有状态组件中,而所有可视化和格式化逻辑应该向下游移动到许多无状态组件中。

来源

  • 有关“道具”和“状态”的问题 – Google网上论坛
  • 反思:确定你的国家应该生活在哪里

基本上,道具和状态是组件可以知道什么以及如何呈现的两种方式。 应用程序状态的哪个部分属于状态,哪个顶级商店更适合您的应用程序devise,而不是React的工作方式。 决定IMO最简单的方法就是思考,这个特定的数据对整个应用程序是否有用,还是一些本地信息。 另外,不重复状态也是很重要的,所以如果某些数据可以从道具上计算出来,就应该从道具上计算出来。

例如,假设您有一些下拉控件(包括标准HTMLselect自定义样式),可以a)从列表中select一些值,以及b)打开或closures(即显示或隐藏选项列表)。 现在,假设您的应用程序显示某种types的项目列表,并且您的下拉列表控件筛选列表条目。 然后,最好将有效的filter值作为道具来传递,并保持本地的开启/closures状态。 此外,为了使其function正常,您可以从父组件传递一个onChange处理程序,该处理程序将在内部下拉元素中调用,并将更新信息(新选定的筛选器)立即发送到商店。 另一方面,打开/closures状态可以保留在下拉组件中,因为应用程序的其余部分并不在乎控件是否打开,直到用户实际改变它的值。

下面的代码不完全工作,它需要CSS和处理下拉式点击/模糊/改变事件,但我想保持最小的例子。 希望它有助于理解差异。

 const _store = { items: [ { id: 1, label: 'One' }, { id: 2, label: 'Two' }, { id: 3, label: 'Three', new: true }, { id: 4, label: 'Four', new: true }, { id: 5, label: 'Five', important: true }, { id: 6, label: 'Six' }, { id: 7, label: 'Seven', important: true }, ], activeFilter: 'important', possibleFilters: [ { key: 'all', label: 'All' }, { key: 'new', label: 'New' }, { key: 'important', label: 'Important' } ] } function getFilteredItems(items, filter) { switch (filter) { case 'all': return items; case 'new': return items.filter(function(item) { return Boolean(item.new); }); case 'important': return items.filter(function(item) { return Boolean(item.important); }); default: return items; } } const App = React.createClass({ render: function() { return ( <div> My list: <ItemList items={this.props.listItems} /> <div> <Dropdown onFilterChange={function(e) { _store.activeFilter = e.currentTarget.value; console.log(_store); // in real life, some action would be dispatched here }} filterOptions={this.props.filterOptions} value={this.props.activeFilter} /> </div> </div> ); } }); const ItemList = React.createClass({ render: function() { return ( <div> {this.props.items.map(function(item) { return <div key={item.id}>{item.id}: {item.label}</div>; })} </div> ); } }); const Dropdown = React.createClass({ getInitialState: function() { return { isOpen: false }; }, render: function() { return ( <div> <select className="hidden-select" onChange={this.props.onFilterChange} value={this.props.value}> {this.props.filterOptions.map(function(option) { return <option value={option.key} key={option.key}>{option.label}</option> })} </select> <div className={'custom-select' + (this.state.isOpen ? ' open' : '')} onClick={this.onClick}> <div className="selected-value">{this.props.activeFilter}</div> {this.props.filterOptions.map(function(option) { return <div data-value={option.key} key={option.key}>{option.label}</div> })} </div> </div> ); }, onClick: function(e) { this.setState({ isOpen: !this.state.isOpen }); } }); ReactDOM.render( <App listItems={getFilteredItems(_store.items, _store.activeFilter)} filterOptions={_store.possibleFilters} activeFilter={_store.activeFilter} />, document.getElementById('root') ); 

状态是反应处理您的组件所持有的信息的方式。

假设您有一个组件需要从服务器获取一些数据。 您通常会想要通知用户请求是否正在处理,是否失败等。这是一个与该特定组件相关的信息。 这是国家进入游戏的地方。

通常定义状态的最好方法如下:

 class MyComponent extends React.Component { constructor() { super(); this.state = { key1: value1, key2: value2 } } } 

但在反应原生最新的实现中,你可以这样做:

 class MyComponent extends React.Component { state = { key1: value1, key2: value2 } } 

这两个示例以完全相同的方式执行,这只是一个语法改进。

那么,和我们在面向对象编程中一直使用的对象属性有什么不同呢? 通常情况下,您所在州的信息并不是静态的,它会随着时间的推移而变化,您的视图将需要更新以反映这种变化。 State以简单的方式提供了这个function。

国家意思是不可侵犯的! 对此我不能给予足够的重视。 这是什么意思? 这意味着你不应该这样做。

  state.key2 = newValue; 

正确的做法是:

 this.setState({ key2: newValue }); 

使用this.setState,组件会在更新周期中运行,并且如果状态的任何部分发生更改,则将再次调用Component render方法以反映此更改。

查看反应文档以获取更多解释: https : //facebook.github.io/react/docs/state-and-lifecycle.html

在回答关于道具是不可改变的最初问题时,就儿童部分而言 ,他们被认为是不可改变的但在父母中是可以改变的。