将异步获取的数据传递给子道具
Posted
技术标签:
【中文标题】将异步获取的数据传递给子道具【英文标题】:Passing asynchronously acquired data to child props 【发布时间】:2016-03-29 03:57:25 【问题描述】:我正在制作一个应用程序,它从远程源获取一系列新闻项目并将它们显示在页面上。
我有端点,并且可以使用$.getJSON()
进行成功的调用,控制台日志证明了这一点。我将此调用放入父组件中,因为子组件将需要使用数据。
但是,当我将此数据传递给子组件时,会出现控制台错误:
Uncaught TypeError: Cannot read property 'headline' of undefined
这是因为 React 甚至在数据传入组件之前就尝试渲染组件。这让我觉得我应该首先在 componentDidMount
以外的地方调用我的 ajax。
为了解决这个问题,我在子组件上设置了一个方法,如果 prop 存在则返回标题:
getHeadline: function ()
if(this.props.newsItems)
return this.props.newsItems.headline
else
return null
,
这感觉有点令人讨厌。有没有更好的方法,还是我的代码中遗漏了什么?
var BigStory = React.createClass(
getHeadline: function ()
if(this.props.newsItems)
return this.props.newsItems.headline
else
return null
,
render: function ()
console.log('props:', this.props);
console.log('newsItems:', this.props.newsItems);
return (
<div className="big-story col-xs-12">
<div className="col-sm-5">
<h1>this.getHeadline()</h1>
<p>Placeholder text here for now.</p>
<p>time | link</p>
</div>
<div className="col-sm-7">
<img src="http://placehold.it/320x220" />
</div>
</div>
);
);
var Main = React.createClass(
getInitialState: function ()
return
newsItems: []
,
componentDidMount: function ()
this.getNewsItems();
,
getNewsItems: function ()
$.getJSON('http://www.freecodecamp.com/news/hot', (data) =>
console.log('data sample:', data[0]);
this.setState(newsItems: data)
)
,
render: function ()
return (
<div className="container">
<div className="main-content col-sm-12">
<div className="left-sided-lg-top-otherwise col-lg-8 col-md-12 col-sm-12 col-xs-12">
<BigStory newsItems=this.state.newsItems[0]/>
</div>
</div>
</div>
);
);
【问题讨论】:
【参考方案1】:我建议将它留给父级来决定当它处于“加载”状态时要做什么,并将 BigStory
作为一个“哑”组件,假设它总是会收到一个有效的 @ 987654322@.
在这个例子中,我展示了一个<LoadingComponent />
,但这可能是你需要的任何东西。这个概念是BigStory
不必担心“接收无效数据”的边缘情况。
var Main = React.createClass(
// ...
render()
const newsItems = this.state;
// You could do this, pass down `loading` explicitly, or maintain in state
const loading = newsItems.length === 0;
return (
<div className="container">
<div className="main-content col-sm-12">
<div className="left-sided-lg-top-otherwise col-lg-8 col-md-12 col-sm-12 col-xs-12">
loading
? <LoadingComponent />
: <BigStory newsItem=newsItems[0] />
</div>
</div>
</div>
);
);
function BigStory(props)
// Render as usual. This will only be used/rendered w/ a valid
return (
<div className="big-story col-xs-12">
<h1>props.headline</h1>
/* ... */
</div>
)
另一种解决方案(尽管我推荐一种更像上面的方法)是始终以相同的方式使用 BigStory
组件,但在没有加载故事时为其提供“占位符故事”。
const placeholderNewsItem =
headline: 'Loading...',
/* ... */
;
var Main = React.createClass(
// ...
render()
const newsItems = this.state;
// Conditionally pass BigStory a "placeholder" news item (i.e. with headline = 'Loading...')
const newsItem = newsItems.length === 0
? placeholderNewsItem
: newsItems[0];
return (
<div className="container">
<div className="main-content col-sm-12">
<div className="left-sided-lg-top-otherwise col-lg-8 col-md-12 col-sm-12 col-xs-12">
<BigStory newsItem=newsItem />
</div>
</div>
</div>
);
);
【讨论】:
这是一个非常有帮助的答案,非常感谢。很高兴看到你也可以使用 ES6。【参考方案2】:这是一个很常见的场景。约翰卡彭特的方法会奏效。我经常使用的另一种方法是创建某种类型的带有微调器图像的Loading
组件(或者您可能用来表示数据正在传输的任何其他方法)。然后,在客户端等待数据到达时,您可以渲染该Loading
组件。例如:
render: function ()
if (this.state.newsItems.length === 0) return <Loading />;
return (
<div className="container">
<div className="main-content col-sm-12">
<div className="left-sided-lg-top-otherwise col-lg-8 col-md-12 col-sm-12 col-xs-12">
<BigStory newsItems=this.state.newsItems[0]/>
</div>
</div>
</div>
);
【讨论】:
【参考方案3】:您可以这样做的一种方法是将this.props.newsItems.headline
设置为“正在加载...”,以向用户指示数据即将到来。
【讨论】:
以上是关于将异步获取的数据传递给子道具的主要内容,如果未能解决你的问题,请参考以下文章