У меня есть компонент более высокого порядка, который устанавливает некоторые значения, а затем передает их как props в wrappedComponent, однако внутри этого завернутого компонента, когда я обращаюсь к this.props из componentDidMount (), значения остаются пустыми. Если я помещаю журналы "this.props" из метода рендеринга в wrappedComponent, тем не менее, я получаю желаемые результаты, хотя я предполагаю, что это из-за повторного рендеринга. Что я здесь делаю не так?
Home.js
import React, { Component } from 'react'
// eslint-disable-next-line
import { BrowserRouter as Router } from 'react-router-dom'
import { Route, Switch } from 'react-router-dom'
import BlogSummaryContainer from './utility/BlogSummaryContainer'
import BlogPost from './utility/BlogPost'
import EditableBlogPost from './utility/EditableBlogPost'
function withBlogPostData (WrappedComponent) {
return class BlogPostContainer extends React.Component {
constructor () {
super()
this.state = { title: '', content: '', catchPhrase: '' }
}
componentDidMount () {
fetch(`/api/posts/${this.props.match.params.id}`)
.then(res => {
return res.json()
})
.then(blogPost => {
// this setState doesnt reach the wrappedComponent in time even if i dont do a fetch and simply hard code a value, whats going on?
this.setState({
title: blogPost.title,
content: blogPost.content,
catchPhrase: blogPost.catchPhrase
})
})
}
render () {
return (
<WrappedComponent
id = {this.props.match.params.id}
title = {this.state.title}
content = {this.state.content}
catchPhrase = {this.state.catchPhrase}
/>
)
}
}
}
class Home extends Component {
... other code
render () {
return (
<Switch>
<Route
exact
path = {`${this.props.match.url}`}
render = {() => {
return <BlogSummaryContainer posts = {this.state.blogPosts} />
}}
/>
<Route
exact
path = {`${this.props.match.url}/:id`}
component = {withBlogPostData(BlogPost)}
/>
<Route
exact
path = {`${this.props.match.url}/:id/edit`}
component = {withBlogPostData(EditableBlogPost)}
/>
<Route
exact
path = {`${this.props.match.url}/new/post`}
render = {() => {
return <EditableBlogPost isNew />
}}
/>
</Switch>
)
}
}
export default Home
EditableBlogPost.js
componentDidMount (props) {
const { title, catchPhrase, content } = this.props
console.info('this.props', this.props) // this.props = {title: "", content: "", ... }
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я думаю, что это просто асинхронная проблема - когда ваш HOC монтируется, он вызывает fetch(), который не решается мгновенно, поэтому при первом рендеринге this.state.x являются их начальными пустыми значениями.
Когда обещание разрешено, значения устанавливаются, и последующий render будет иметь ожидаемые значения.
Вы можете условно выполнить рендеринг, чтобы избежать рендеринга обернутого компонента, пока fetch() не разрешится:
render () {
if (this.state.title.length === 0) {
return <div>Loading...</div>; //or some nice <Loading> component
}
return (
<WrappedComponent
id = {this.props.match.params.id}
title = {this.state.title}
content = {this.state.content}
catchPhrase = {this.state.catchPhrase}
/>
)
}
когда вы говорите, что жестко кодируете значения, вы имеете в виду в constructor() или в вызове setState()?
componentDidMount () { this.setState({ title: 'hello world' }) } Это дает тот же результат, что и при выборке. т.е.: title: "", content: "", catchPhrase: ""}
setState() также не обновляет состояние мгновенно. Попробуйте ввести значения для this.state = {} в constructor(), и я подозреваю, что это может сработать.
Однако мне нужно сделать выборку на серверной части. что, насколько я понимаю, это не то, что вы делаете в конструкторе
используя componentWillMount () (не componentDidMount), я могу установитьState ({title: 'hello world'}), хотя я все еще не могу заставить его работать с fetch (). Насколько я понимаю, componentDidMount предназначен для асинхронных действий и, следовательно, должен работать для этого?
Он будет работать, но компонент смонтирован так, что это означает, что обернутый компонент отрендерил, НО ваша выборка еще не решена.
Вы правы, поэтому кажется, что это потому, что componentDidMount в wrappedComponent вызывается слишком рано, и поскольку он вызывается только дважды, он не будет иметь правильных результатов. Он работает с условием, указанным вами выше. Спасибо!
есть ли более элегантный способ сделать это?
Позвольте нам продолжить обсуждение в чате.
Решение, указанное Тони, на самом деле было решением проблемы.
К сожалению, это не так, даже без выборки, просто жесткое кодирование значений тоже не работает. Единственная причина, по которой я включил пример как есть, потому что в противном случае мне сказали бы просто выполнить настройку переменной в конструкторе.