我正在将Wordpress API与React和Redux结合使用。我设法通过API从Wordpress博客(从另一个URL)获得了几个帖子。一切都很精彩,我可以跨域发布帖子并将它们加载到Redux商店,在页面上呈现它们等。
但有一点我无法理解:对于一页上的单个帖子,我如何才能从商店访问和呈现一个帖子?
我认为我非常接近,当我直接发出行动时,我已经收到了帖子。
但是现在对于单页,我已经在商店中发帖了。我连接到商店,想要通过URL的slug获得一个帖子。
我的想法如下:
import { withRouter } from 'react-router-dom';
import { connect, mapStateToProps } from 'react-redux';
@connect((store) => {
return {
posts: store.posts,
postsFetched: store.posts.fetched,
users: store.users.users,
usersFetched: store.users.fetched
};
})
class SinglePost extends React.Component {
constructor(props){
super(props);
this.state = {
title: 'Some test title',
singlePost: '',
pathname: ''
}
}
componentWillMount() {
//Get the pathname
var {pathname} = this.props.location;
//remove the / in front of pathname and put pathname into parantheses
if(pathname.charAt(0) === "/")
var pathname = pathname.slice(1);
console.log('pathname is:', pathname);
this.setState({
pathname: pathname
});
for(var i = 0; i < this.props.posts.posts.length; i++) {
if(this.props.posts.posts[i].slug == this.state.pathname){
this.setState((prevState, props) => ({
singlePost: this.props.posts.posts[i],
title: this.props.posts.posts[i].title.rendered
}));
const singlePost = this.props.posts.posts[i];
console.log('singlePost was fired');
} else {
console.log('singlePost was not fired');
}
}
}
render() {
return (
<div className="container">
<h2 className="text-center">{ this.state.singlePost.title }</h2>
</div>
);
}
}
export default connect(mapStateToProps) (SinglePost);
我得到btw的路径名。我为for循环尝试了其他几个地方(shouldComponentUpdate,componentWillReceiveProps等),但是组件没有渲染,或者我得到了singlePost.title但是在无限循环中。
显然,当我已经将所有内容加载到商店中时,我不想再对API做任何事情,只需将其发布到商店外即可。
任何想法,我可以研究的事情,建议?
答案 0 :(得分:1)
尝试通过slug键入你传入的帖子数据,这样你的帖子数据的形状就是这样。
posts: {
slug_1: { ... },
slug_2: { ... }
};
这允许您在需要时直接通过slug抓取它,而不必遍历潜在的大型对象数组。
state.posts[slug]
你可以在你的reducer中重塑你传入的帖子数据:
return data.map(post => ({[post.slug]: post}))
我个人建议在你的functions.php中编写一个小的自定义函数来处理一个slug查询并返回那个帖子,从而消除了对这种客户端工作的需要。
这看起来像是:
function get_post_from_slug($data) {
$slug = $data['slug'];
$post = get_page_by_path($slug, OBJECT, array('post'));
return new WP_REST_Response($post, 200);
}
add_action( 'rest_api_init', function() {
$version = '/v1';
$namespace = 'my-awesome-api' . $version;
register_rest_route( $namespace, '/post' , array(
'methods' => 'GET',
'callback' => 'get_post_from_slug',
));
});
// Endpoint
../wp-json/my-awesome-api/v1/post?slug=slug_1
希望这有帮助!
答案 1 :(得分:1)
感谢@Anthony的回答,我得到了一个更好的基本想法,而不是从API获取一个帖子(而不是从数组中的所有帖子中过滤出来)
以下是我的代码的外观:
import { withRouter } from 'react-router-dom';
import { connect, mapStateToProps } from 'react-redux';
import { getPostByURL } from 'redux/actions/postsActions.js';
@connect((store) => {
return {
singlePost: store.singlePost,
singlePostFetched: store.singlePost.fetched,
users: store.users.users,
usersFetched: store.users.fetched
};
})
class SinglePost extends React.Component {
constructor(props){
super(props);
this.state = {
pathname: ''
}
}
componentWillMount() {
//Get the pathname
var {pathname} = this.props.location;
//remove the / in front of pathname and put pathname into parantheses
if(pathname.charAt(0) === "/")
var pathname = pathname.slice(1);
this.setState({
pathname: pathname
});
this.props.dispatch(getPostByURL(pathname));
}
render() {
const { users, singlePost } = this.props;
return (
<div className="container">
{singlePost.singlePost.map(post => {
return(
<div>
<h1>{post.title.rendered}</h1>
</div>
);
})}
</div>
);
}
}
export default connect() (SinglePost);
我的postsActions.js的一部分:
export function getPostByURL(pathname) {
return function(dispatch){
console.log(pathname);
axios.get(`http://example.com/wp-json/wp/v2/posts/?filter[name]=${pathname}&_embed`)
.then((response) => {
dispatch({type: 'FETCH_POST_BY_URL_FULFILLED', payload: response.data});
})
.catch((err) => {
dispatch({type: 'FETCH_POST_BY_URL_REJECTED', payload: err})
})
}
}