大家好, 这是我关于Stack Overflow的第一篇文章,但我会尽力遵守正确的格式!总而言之,我在此react组件上花费了最后五个小时,试图呈现通过孩子的道具从父组件状态传递过来的对象的列表。我尝试了每种方式,研究了多种解决方案,但似乎没有任何效果。这是我第一次使用webpack,也许我需要下载一些插件才能使用React状态和道具?我不知道。无论如何,我将在下面发布摘要,并尽我所能描述每个步骤。
在这一点上,我没有遇到任何麻烦,我已经记录了结果的每一步,因此对于事实,我知道 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开发工具,该工具向您显示哪些组件具有道具和状态。您可以在此图中看到子组件 did 收到了预期的道具并相应地更新了其状态。 但是再次,由于某种原因,它不允许我访问它们并显示结果
如果这个问题太冗长,我真的道歉...是的,我知道已经解决了多个类似的帖子,但是我查看了其中的大多数帖子,但是我的情况并不适用我的情况...我不是专家,但我不是新手。这真让我难过。 非常感谢您的帮助。如果有帮助,我可以提供其他屏幕截图,代码段甚至视频!
makezi
我添加了用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>
}
}
我将父母的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>
}
}
需要重申的是,在我的组件中,receiveprops函数是:“ console.log('nextProps.weatherArray)”会发出完整的数据数组...但是,“ console.log('this.state.currentWeather” )“ 才不是。即使在setState运行之后。但是,当我使用React Chrome Dev Tools时,您可以看到脸上的状态DID传递给了子组件。我的渲染方法由于某种原因无法读取数据。
第一个片段是我的父组件。您会看到它正在将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之后,我将发布孩子的代码段。现在,我不再尝试显示处于孩子状态的数据,而只是尝试使用从孩子的父组件传递来的道具数据。不幸的是,我仍然遇到同样的问题。我孩子的render函数正在读取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
查看上面的两个屏幕截图。第一个是在我运行提取功能之前,因此React Chrome Dev Tools显示我孩子的props数组为空(当然)。但是之后的屏幕截图显示,即使React React Tools显示我的子组件的props具有完整的数组,我的render方法仍然读取该prop数组的长度为0。...
答案 0 :(得分:0)
首先,getWeather
函数正在获取Weatherbit API,因此您必须使用await
提取功能。在上面的代码中,我认为您使用函数WeatherHelper.inputPrompt()
来获取数据,因此该函数将是:
async getWeather() {
const newWeather = await WeatherHelper.inputPrompt();
console.log(newWeather)
this.setState({weatherArray: newWeather})
WeatherHelper.showData()
}
在上面的代码中,console.log
是打印数据,因为它可以异步打印数据(根据我的经验)。
第二,您不应该将数组与!==进行比较,请阅读this。
请更改您的代码,如果不起作用,请在componentWillReceiveProps中记录nextProps数据和Child组件的状态,并向我显示其屏幕截图。
对不起,我的英语不好。
答案 1 :(得分:0)
您不需要使用componentWillReceiveProps。这给您增加了很多不必要的复杂性。当父组件的状态发生变化时,它将自动重新渲染其子组件。省略componentWillReceiveProps并使用this.props.weatherArray在子组件中进行渲染。
答案 2 :(得分:0)
反应文档建议避免使用遗留生命周期,例如componentWillReceiveProps。
一个常见的误解是,仅在道具“更改”时才调用getDerivedStateFromProps和componentWillReceiveProps。每当父组件重新渲染时,这些生命周期都将被调用,而不管道具是否与之前“不同”。因此,使用这些生命周期中的任何一个无条件地覆盖状态始终是不安全的。这样做会导致状态更新丢失。
文档说:
componentDidMount()在安装组件后立即被调用...如果您需要从远程端点加载数据,这是实例化网络请求的好地方。
编辑:
查看第三次编辑,我一直假设您是通过componentDidMount
生命周期来获取呼叫,因为您一直在迭代获取“作品”的过程。
由于上述代码段实际上并未显示componentDidMount
方法,因此建议尝试将所有提取逻辑移至相应的componentDidMount
方法,然后从那里设置状态。