【发布时间】:2020-01-21 02:09:13
【问题描述】:
大家好, 这是我在 Stack Overflow 上的第一篇文章,但我会尽力遵守正确的格式!总而言之,我在这个 react 组件上花费了最后五个小时,试图通过子组件的 props 呈现从父组件的状态向下传递的对象列表。我已经尝试了所有方法,研究了多种解决方案,但似乎没有任何效果。这是我第一次使用 webpack,也许我必须下载一些插件才能使用 React 状态和道具?我不知道。无论如何,我将在下面发布 sn-ps,并尽我所能描述每个步骤。
我的家长应用
这方面我没有遇到任何问题,我已经记录了每一步的结果,所以我知道 事实 getWeather 函数正在正确获取数据来自 Weatherbit API 并设置状态,正如您将看到的那样,它又通过它的 props 将数组传递给子节点。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {weatherArray: []}
this.getWeather = this.getWeather.bind(this);
}
getWeather() {
const newWeather = WeatherHelper.inputPrompt();
console.log(newWeather)
this.setState({weatherArray: newWeather})
WeatherHelper.showData()
}
仍在我的父母应用中
如您所见,我将状态作为道具传递给孩子,它会在 setState 运行时立即更新
<div id='side-apps'>
<div id='weather-side-app'>
<WeatherApp weatherArray={this.state.weatherArray} />
</div>
</div>
我的孩子应用
所以这就是奇怪的地方...... 这是我的子组件,正如您所看到的,当组件收到新的道具时,它首先检查这些道具是否已更新。然后,假设这些道具是新的,componentWillReceiveProps 方法将设置状态并相应地重新渲染(或者你会这么想)。您还可以看到我已经广泛使用日志记录来尝试记录我的问题,接下来我将提供一个屏幕截图。请注意,在 componentWillReceiveProps 方法中,如果道具与原始道具不同(即更新),该方法将在更新的道具周围记录多个破折号,以便您可以指出它们(您会看到)。顺便说一句,我知道我什至不应该使用 componentWillReceiveProps 方法,单独的父 setState 函数应该足以更新我的组件,但可惜没有(我尝试的其他 10 种不同的方法也没有)。
class WeatherApp extends React.Component {
constructor(props) {
super(props);
this.state = {currentWeather: []}
}
handleCloseClick() {
WeatherHelper.hideData();
}
componentWillReceiveProps(nextProps) {
if (nextProps.weatherArray !== this.state.currentWeather) {
console.log('---')
console.log(nextProps.weatherArray)
console.log('---')
this.setState({currentWeather: nextProps.weatherArray})
} else {
{console.log("if you see an array under this comment," +
"that means the above if statement read the state's
currentWeather array's length" +
" as zero. EVEN THOUGH the componentWillReceiveProps method" +
" updated and set the state accordingly...")}
console.log(nextProps.weatherArray)
console.log(this.state.currentWeather)
}
}
render() {
if (this.state.currentWeather.length > 0) {
return (
<div class='weatherApp-main'>
<div className='close-sidebar-button'>
<img src='https://i.postimg.cc/hj0rYKxc/close-button.png' onClick={this.handleCloseClick}/>
</div>
<div id='weather-app-header'>
<h2>{this.state.currentWeather}</h2>
<h3></h3>
<h4></h4>
</div>
<div id='weather-app-table'>
</div>
</div>
)
} else {
{console.log(this.state.currentWeather)}
return <p></p>
}
}
}
子组件日志记录详细信息
如果您查看屏幕截图,您可以看到我从我孩子的 componentWillReceiveProps 方法中记录的日志证明 setState 函数必须已被调用,但出于某种原因它不会更新孩子的 html 和显示数据。
child component logging details
子组件反应细节
好的,最后一件事...我还发布了 react chrome 开发工具,它向您展示了哪些组件具有道具和状态。您可以在这张图片中看到,子组件确实收到了预期的道具并相应地更新了它的状态。 但同样,由于某种原因,它不允许我访问它们并显示结果
如果这个问题太长,我真的很抱歉......是的,我知道已经解决了多个类似的帖子,但我已经查看了其中的大部分,我的情况并不适用于我所知道的......我不是专家,但我不是反应的新手。这真的难倒我。 非常感谢您的帮助。如果有帮助,我可以提供额外的屏幕截图、代码 sn-ps 甚至视频!!!
制作子
编辑
我添加了用 map 函数替换代码块,如您所见,问题不在于我如何将数据传递到 DOM。问题是由于某种原因,我的组件没有读取其状态的数据(我将发布更详细的屏幕截图以更好地记录问题)
render() {
console.log('++++')
console.log(this.state.currentWeather.length);
if (this.state.currentWeather.length > 0) {
return (
<div class='weatherApp-main'>
<div className='close-sidebar-button'>
<img src='https://i.postimg.cc/hj0rYKxc/close-button.png' onClick={this.handleCloseClick}/>
</div>
<div id='weather-app-header'>
{this.state.currentWeather.map(item => <div><span>{item.city}</span></div>)}
<h3></h3>
<h4></h4>
</div>
<div id='weather-app-table'>
</div>
</div>
)
} else {
{console.log("if you see an array under this comment," +
"that means the above if statement read the state's currentWeather array's length" +
" as zero. EVEN THOUGH the componentWillReceiveProps method" +
" updated and set the state accordingly...")}
{console.log(this.state.currentWeather)}
return <p></p>
}
}
Minh Hưng Trần 评论的第二次编辑
我将我父母的 getWeather 函数更新为异步,还编辑了日志以更具描述性。您可以看到 即使 state 中的 currentWeather 数组有 8 个对象,长度仍被读取为零!我认为问题不在于比较数组。出于某种原因,我的渲染函数无法读取我的状态中的数据......或者运行 setState 时它没有被更新。 **您无法从屏幕截图中看出,但 nextProps 数组已被读取并完全记录到控制台。虽然在运行 setState 之后,''console.log(this.state.currentWeather)'' 记录了一个空数组,很奇怪吧? **
componentWillReceiveProps(nextProps) {
if (nextProps.weatherArray !== this.state.currentWeather) {
console.log("--nextProps weatherArray--")
console.log(nextProps.weatherArray)
console.log('--------------------------')
this.setState({currentWeather: nextProps.weatherArray})
console.log("==child's state==")
console.log(this.state.currentWeather)
console.log("=================")
} else {
console.log(nextProps.weatherArray)
console.log(this.state.currentWeather)
}
}
render() {
console.log("++child's state's length in render method++")
console.log(this.state.currentWeather.length);
console.log("+++++++++++++++++++++++++++++++++++++++++++")
if (this.state.currentWeather.length > 0) {
return (
<div class='weatherApp-main'>
<div className='close-sidebar-button'>
<img src='https://i.postimg.cc/hj0rYKxc/close-button.png' onClick={this.handleCloseClick}/>
</div>
<div id='weather-app-header'>
{this.state.currentWeather.map(item => <div><span>{item.city}</span></div>)}
<h3></h3>
<h4></h4>
</div>
<div id='weather-app-table'>
</div>
</div>
)
} else {
{console.log("if you see an array under this comment," +
"that means the above if statement read the state's currentWeather array's length" +
" as zero. EVEN THOUGH the componentWillReceiveProps method" +
" updated and set the state accordingly...")}
{console.log(this.state.currentWeather)}
return <p></p>
}
}
重申一下,在我的 componentwillreceiveprops 函数中:“console.log('nextProps.weatherArray)”确实会发出完整的数据数组......但是,“console.log('this.state.currentWeather )“ 才不是。即使在 setState 运行之后。但是当我使用 React Chrome 开发工具时,你可以看到 face 中的状态 DID 被传递给了子组件。我的渲染方法由于某种原因无法读取数据..
第三次编辑
第一个 sn-p 是我的父组件。您可以看到它正在将 weatherArray 传递给孩子的道具。顺便说一下,这个 getWeather 函数确实有效,我一直在通过日志记录来验证它。问题出在我孩子的头上,我很确定。
class App extends React.Component {
constructor(props) {
super(props);
this.state = {weatherArray: []}
this.getWeather = this.getWeather.bind(this);
}
async getWeather() {
const newWeather = await WeatherHelper.inputPrompt();
console.log(newWeather)
this.setState({weatherArray: newWeather})
WeatherHelper.showData()
}
render() {
return (
<div>
<div id='main'>
<div id='introduction'>
<Intro />
</div>
<div id='attachment'>
<Attachment getWeather={this.getWeather} />
</div>
<div id='body'>
<div id='about'>
<About />
</div>
<div id='personal-info-skills'>
<div id='info'>
<p id='info-header'>personal information</p>
<Info />
</div>
<div id='pskills'>
<p id='pskills-header'>personal skills</p>
<PSkills />
</div>
</div>
<div className='divider'>
<p></p>
</div>
<div id='professions-languages'>
<div id='professions'>
<p id='professions-header'>professions</p>
<Professions />
</div>
<div id='languages'>
<p id='languages-header'>languages</p>
<Languages />
</div>
</div>
</div>
</div>
<div id='side-apps'>
<div id='weather-side-app'>
<WeatherApp weatherArray={this.state.weatherArray} />
</div>
</div>
</div>
)
}
}
现在我将在注释掉 componentWillReceiveProps 后发布我孩子的代码 sn-p。现在我只是尝试使用从孩子的父组件传递的道具数据,而不是尝试以我孩子的状态显示数据。不幸的是,我仍然遇到同样的问题。我孩子的渲染函数将 props 数组读取为空,因此无法显示数据。我不能在 render 方法的开头删除 if 语句,因为我的代码在尝试读取空数组的属性时会抛出错误
render() {
if (this.props.weatherArray.length > 0) {
return (
<div class='weatherApp-main'>
<div className='close-sidebar-button'>
<img src='https://i.postimg.cc/hj0rYKxc/close-button.png' onClick={this.handleCloseClick}/>
</div>
<div id='weather-app-header'>
{this.props.weatherArray.map(item => <div><span>{item.city}</span></div>)}
<h3></h3>
<h4></h4>
</div>
<div id='weather-app-table'>
</div>
</div>
)
} else {
{console.log("if you see an array under this comment," +
"that means the above if statement read the state's currentWeather array's length" +
" as zero. EVEN THOUGH the React Chrome Dev Tools shows that" +
" the child has a full currentWeather array in props...")}
{console.log(this.state.currentWeather)}
return <p></p>
}
}
}
before running getWeather function screen shot
after running getWeather function screen shot
看上面两张截图。第一个是在我运行我的 fetch 函数之前,所以 React Chrome 开发工具显示我孩子的 props 数组是空的(当然)。但是之后的屏幕截图显示,即使 React 开发工具显示我的子组件的道具有一个完整的数组,我的渲染方法仍然将该道具数组的长度读取为 0....
【问题讨论】:
-
我不确定您为什么要尝试在 h2 标记中显示 currentWeather,因为 currentWeather 是一个包含对象的数组 - 这应该会引发错误。我建议用.map循环它,即this.state.currentWeather.map(item =>{item.city}...)
-
我试过了,我现在就做给你看。对不起,我应该恢复正常。感谢您的回复!
-
如果你在编辑完一段代码后查看屏幕截图,我对其进行了更改,因此它也显示了 react 组件的 props & state。它清楚地表明 currentWeather 数组中充满了数据......我无法弄清楚为什么我的渲染方法没有获取该数据。 如果有人想查看完整代码,我可以添加一个指向 git-hub 存储库的链接,请问!
-
请告诉我们您在哪里调用 getWeather。
-
setState是一种异步方法,因此您的 console.log 仍可能打印空数组。您可以通过执行setState({currentWeather: nextProps.weatherArray}, () => console.log(this.state))来测试这一点,这将在完成setState后将console.log 函数作为回调运行。此外,是否有任何特定情况为什么您的子组件必须保持与父组件相同数组的状态?我敢打赌componentWillReceiveProps是这里的问题,因为它是一个同步函数(在处理异步获取时会收到不匹配的渲染,因此自 React 16.3 起它就被弃用了)
标签: javascript reactjs components state