我正在将React与Wordpress REST API一起使用。我遇到的问题是,当根Post
组件上的Slug属性更改并获取异步数据时,我似乎无法全神贯注于如何(正确)使用组件生命周期来更新App
组件。
我目前设置的方式,App
组件状态如下所示:
this.state = {
pages: this.getPages(),
slug: this.getSlug(),
homePage: this.fetchPost('home'),
};
因此,pages
属性是一个promise,App组件最初将呈现Spinner组件。最终,异步调用收到响应。我对发布对象数组执行过滤,以查找当前页面发布。
const thePage = this.state.pages.filter(page => {
return page.slug === slug;
});
过滤器返回一个带有一个对象的数组(当前页面)。我用this.setState({post: thePage[0]});
当我使用react-router-dom
更改更改路由时,slug
和post
没有更新。下面是我的代码。
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './components/App/App';
// Take the React component and show it on the screen
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root'));
App JS:
// App.js
import React, {Component} from 'react';
import { Route, withRouter } from 'react-router-dom';
import axios from 'axios';
import './App.scss';
import {wpAPI} from '../..//api';
import {/*loadState,*/ saveState} from '../loadState/loadState';
import FrontPage from '../../pages/FrontPage';
import Header from '../Header/Header';
import Post from '../Post/Post';
import Sidebar from '../Sidebar/Sidebar';
import Footer from '../Footer/Footer';
import Spinner from '../Spinner/Spinner';
// Create a React Component
class App extends Component {
constructor(props) {
super(props);
// Bindings
this.getPages = this.getPages.bind(this);
this.getPages();
this.state = {
isHome: false,
slug: this.props.location.pathname,
fetchingPages: true,
fetchingPost: true,
};
console.log('App State: (constructor)');
console.log(this.state);
}
/**
* Fetch Data
* @return {Promise}
*/
getPages = async () => {
const response = await axios.get(wpAPI['pages']);
this.setState({
fetchingPages: false,
pages: response.data
});
saveState(this.state);
}
getPage = (slug) => {
const thePage = this.state.pages.filter(page => {
return page.slug === slug.replace('/', '');
});
this.setState({
isHome: false,
fetchingPost: false,
post: thePage[0],
slug: slug,
});
}
/**
* The component has mounted. Fetch post based on slug
*/
componentDidMount() {
console.log('App State: (componentDidMount)');
console.log(this.state);
console.log('App Props: (componentDidMount)');
console.log(this.props);
}
componentDidUpdate(prevProps, prevState) {
console.log('App State: (componentDidUpdate)');
console.log(this.state);
const {fetchingPages, fetchingPost, isHome} = this.state;
const slug = this.props.location.pathname;
if (this.state.slug !== this.props.location.pathname) {
console.log('Slugs Dont match, getting page');
this.getPage(slug);
}
if (slug === '/' && !isHome) {
console.log('Setting isHome True');
this.setState({
isHome: true,
fetchingPost: false
});
}
if (fetchingPages === false && fetchingPost === true) {
console.log('Fetching Post');
this.getPage(slug);
}
}
renderContent() {
const {post, fetchingPost} = this.state;
if (!fetchingPost) {
return (
<section id="app" className="animated fadeIn">
<Header />
<main>
<Route path="/" exact render={(props) => <FrontPage {...props} /> } />
<Route path="/:slug" exact render={(props) => <Post post={post} /> } />
</main>
<Sidebar />
<Footer />
</section>
)
}
return <Spinner message='loading data...' />;
}
render() {
return this.renderContent();
}
};
export default withRouter(App);
Post.js
import React, {Component} from 'react';
import {withRouter} from 'react-router-dom';
import './Post.scss';
import Spinner from '../Spinner/Spinner';
class Post extends Component {
constructor(props) {
super(props);
this.state = {
slug: props.slug,
post: props.post,
};
}
componentDidMount() {
console.log('Post State: (componentDidUpdate)');
console.log(this.state);
}
componentDidUpdate() {
console.log('Post State: (componentDidUpdate)');
}
render() {
if ( this.state.post ) {
const {post} = this.state;
return (
<div className={`post post-${post.id} ${post.slug} animated fadeIn`}>
<header>
<h1 className="small-caps" dangerouslySetInnerHTML={{__html: post.title.rendered}}></h1>
</header>
<section id="content" dangerouslySetInnerHTML={{__html: post.content.rendered}}></section>
</div>
)
}
return <Spinner message='Fetching Post...'/>
}
}
export default withRouter(Post);
答案 0 :(得分:0)
代码中没有什么可以说的是,当您的应用从HttpClient httpClient = new HttpClient();
string html = await httpClient.GetStringAsync("http://www.wordreference.com/definicion/mundo");
HOC接收新道具时,然后更新withRouter
。
您可以添加:
state.slug
到您的this.setState({
slug: this.getSlug();
});
函数,但是我不确定为什么当它在componentDidUpdate()
中仍然可以作为道具被传递给您的FrontPage组件时,为什么需要它作为状态同样可以轻松地传递到您的Posts组件。