如何在 React 组件之间共享 API
How to Share an API Between React Components
我有一个 API returns 所有 objects 系统中的用户所喜爱的 (GET /loves.json
)。我正在展示一组 objects,如果用户喜欢使用 React 的给定产品,我想使用对 API 的单个调用到 'color'。到目前为止我有:
components/love.js.jsx.coffee:
class Components.Love extends React.Component
@propTypes =
id: React.PropTypes.number
type: React.PropTypes.string
constructor: (props) ->
super(props)
@state = Loves.Fetcher.shared()
loved: ->
this.state.loved(@props.id, @props.type)
text: ->
if @loved() then "Loved" else "Unloved"
render: ->
return React.DOM.div {}, @text()
loves/fetcher.js.coffee:
class Loves.Fetcher
instance = null
@shared: -> instance ?= new Loves.Fetcher
constructor: ->
@fetch()
loved: (id, type) ->
return ...
fetch: ->
$.get "/loved.json", (data) -> ...
index.html:
<h1>Shoes</h1>
<div data-react-class="Components.Love" data-react-props="{'id':1,'type':'Product'}"></div>
<h1>Pants</h1>
<div data-react-class="Components.Love" data-react-props="{'id':2,'type':'Product'}"></div>
<h1>Again</h1>
<div data-react-class="Components.Love" data-react-props="{'id':1,'type':'Product'}"></div>
<h1>Pants (Again)</h1>
<div data-react-class="Components.Love" data-react-props="{'id':2,'type':'Product'}"></div>
但是,我不确定如何进行。当状态发生变化(例如通过 HTTP 请求)以让它们更新时,React 通知组件的方式是什么?还有其他分享 API 结果的好方法吗(我绝对不希望每个爱组件都有一个 HTTP 请求)?我希望能够将爱的成分放在任何地方,而不是依赖 parent / child 关系。
创建一个将数据保存为状态的容器组件,并将其作为属性传递给子组件。
子组件将是您编写的 Components.Love
class,但您必须更改这些组件,使它们不具有 loved
作为状态,而是作为 属性是父组件带进来的。
您可能想开始使用 Flux。在 Flux 架构中,您的组件将触发操作,例如 getLove
操作。此操作将被拦截并分派到商店,例如 LoveStore
.
Store
保存代表您的应用程序(或其中的一部分)模型的数据。 Action
修改模型。在您的例子中,由于 getLove
操作,LoveStore
将触发 GET
请求、获取数据并更新模型。
模型更新后,LoveStore
会发布更改。需要该数据的组件将监听 LoveStore
中的变化:一旦它们收到通知,它们就会更新其内部状态。更新它们的内部状态将触发 render()
方法。
您可以看到一些好处:
- 模型与您的组件分离
- API可以集中在不同的文件中(
LoveFetcher
),并由商店调用,唯一可以访问和修改模型的实体
- 使用 publish/subscribe 模式,对数据更改感兴趣的组件会监听适当的存储,仅此而已
- 数据流单向,Flux架构的一大特点,保证了各个组件与页面模型的一致性。
我有一个 API returns 所有 objects 系统中的用户所喜爱的 (GET /loves.json
)。我正在展示一组 objects,如果用户喜欢使用 React 的给定产品,我想使用对 API 的单个调用到 'color'。到目前为止我有:
components/love.js.jsx.coffee:
class Components.Love extends React.Component
@propTypes =
id: React.PropTypes.number
type: React.PropTypes.string
constructor: (props) ->
super(props)
@state = Loves.Fetcher.shared()
loved: ->
this.state.loved(@props.id, @props.type)
text: ->
if @loved() then "Loved" else "Unloved"
render: ->
return React.DOM.div {}, @text()
loves/fetcher.js.coffee:
class Loves.Fetcher
instance = null
@shared: -> instance ?= new Loves.Fetcher
constructor: ->
@fetch()
loved: (id, type) ->
return ...
fetch: ->
$.get "/loved.json", (data) -> ...
index.html:
<h1>Shoes</h1>
<div data-react-class="Components.Love" data-react-props="{'id':1,'type':'Product'}"></div>
<h1>Pants</h1>
<div data-react-class="Components.Love" data-react-props="{'id':2,'type':'Product'}"></div>
<h1>Again</h1>
<div data-react-class="Components.Love" data-react-props="{'id':1,'type':'Product'}"></div>
<h1>Pants (Again)</h1>
<div data-react-class="Components.Love" data-react-props="{'id':2,'type':'Product'}"></div>
但是,我不确定如何进行。当状态发生变化(例如通过 HTTP 请求)以让它们更新时,React 通知组件的方式是什么?还有其他分享 API 结果的好方法吗(我绝对不希望每个爱组件都有一个 HTTP 请求)?我希望能够将爱的成分放在任何地方,而不是依赖 parent / child 关系。
创建一个将数据保存为状态的容器组件,并将其作为属性传递给子组件。
子组件将是您编写的 Components.Love
class,但您必须更改这些组件,使它们不具有 loved
作为状态,而是作为 属性是父组件带进来的。
您可能想开始使用 Flux。在 Flux 架构中,您的组件将触发操作,例如 getLove
操作。此操作将被拦截并分派到商店,例如 LoveStore
.
Store
保存代表您的应用程序(或其中的一部分)模型的数据。 Action
修改模型。在您的例子中,由于 getLove
操作,LoveStore
将触发 GET
请求、获取数据并更新模型。
模型更新后,LoveStore
会发布更改。需要该数据的组件将监听 LoveStore
中的变化:一旦它们收到通知,它们就会更新其内部状态。更新它们的内部状态将触发 render()
方法。
您可以看到一些好处:
- 模型与您的组件分离
- API可以集中在不同的文件中(
LoveFetcher
),并由商店调用,唯一可以访问和修改模型的实体 - 使用 publish/subscribe 模式,对数据更改感兴趣的组件会监听适当的存储,仅此而已
- 数据流单向,Flux架构的一大特点,保证了各个组件与页面模型的一致性。