我正在使用Next.js和React并持续数天解决这个问题。因此,在Next.js页面中,我具有动态页面[postid] .js,如下所示,
import Layout from "../../components/layout";
import { useRouter } from "next/router";
import Singlepost from "../../components/post/singlepost";
export default function Post() {
const router = useRouter();
const postId = router.query.postid
return (
<Layout>
{console.log(router.query.postid)}
<h1>{router.query.postid}</h1>
<p>This is the post content.</p>
<Singlepost postId={postId}/>
</Layout>
);
}
在这里,我将查询参数作为props(postId)发送到singlepost组件。 但是在Singlepost组件中,我尝试在componentDidMount内部使用此道具,然后通过api调用获取数据,但是postId显示为未定义,因此api调用无法获取数据。
componentDidMount() {
const postId = this.props.postId;
console.log("postId:", postId);
singlePost(postId).then(data => {
if (data.error) {
console.log(data.error);
} else {
this.setState({
post: data,
likes: data.likes.length,
like: this.checkLike(data.likes),
comments: data.comments
});
}
});
}
那么我如何在componentDidMount中获得prop值?还是有其他方法可以解决这个问题? 这也是我完整的singlepost.js供参考,
import React, { Component } from "react";
import {
singlePost,
remove,
like,
unlike
} from "../../components/post/apiPost";
import Link from "next/link";
import { isAuthenticated } from "../../components/auth";
import DefaultPost from "../../public/images/courses.png";
import Router, { withRouter } from "next/router";
class SinglePost extends Component {
constructor(props) {
super(props);
this.state = {
post: "",
redirectToHome: false,
redirectToBack: false,
redirectToSignin: false,
like: false,
likes: 0,
comments: [],
};
}
checkLike = likes => {
const userId = isAuthenticated() && isAuthenticated().user._id;
let match = likes.indexOf(userId) !== -1;
return match;
};
componentDidMount() {
const postId = this.props.postId;
console.log("postId:", postId);
singlePost(postId).then(data => {
if (data.error) {
console.log(data.error);
} else {
this.setState({
post: data,
likes: data.likes.length,
like: this.checkLike(data.likes),
comments: data.comments
});
}
});
}
updateComments = comments => {
this.setState({ comments });
};
likeToggle = () => {
if (!isAuthenticated()) {
this.setState({ redirectToSignin: true });
return false;
}
let callApi = this.state.like ? unlike : like;
const userId = isAuthenticated().user._id;
const postId = this.state.post._id;
const token = isAuthenticated().token;
callApi(userId, token, postId).then(data => {
if (data.error) {
console.log(data.error);
} else {
this.setState({
like: !this.state.like,
likes: data.likes.length
});
}
});
};
deletePost = () => {
const postId = this.props.quota;
const token = isAuthenticated().token;
remove(postId, token).then(data => {
if (data.error) {
console.log(data.error);
} else {
this.setState({ redirectToBack: true });
}
});
};
deleteConfirmed = () => {
let answer = window.confirm("Are you sure you want to delete your post?");
if (answer) {
this.deletePost();
}
};
renderPost = post => {
console.log(post);
const posterId = post.postedBy ? `/user/${post.postedBy._id}` : "";
const posterName = post.postedBy ? post.postedBy.name : " Unknown";
const { like, likes, comments } = this.state;
return (
<div className="column">
<img
src={`${process.env.REACT_APP_API_URL}/post/photo/${post._id}`}
alt={post.title}
onError={i => (i.target.src = `${DefaultPost}`)}
className="img-thunbnail"
style={{
height: "300px",
width: "100%",
objectFit: "cover"
}}
/>
<button onClick={this.likeToggle}>
<i className="far fa-thumbs-up text-success bg-dark" />
{likes} Like
</button>{" "}
<span className="button is-primary" onClick={() => Router.back()}>
<strong> Back to posts </strong>
</span>
{isAuthenticated().user &&
isAuthenticated().user._id === post.postedBy._id && (
<>
<span className="button is-warning">
<Link href={`/post/edit/${post._id}`}>
<strong> Update Post </strong>
</Link>
</span>
<button
onClick={this.deleteConfirmed}
className="button is-danger"
>
Delete Post
</button>
</>
)}
<div>
{isAuthenticated().user && isAuthenticated().user.role === "admin" && (
<div class="column">
<div className="columns">
<h5 className="column">Admin</h5>
<p>Edit/Delete as an Admin</p>
<span className="button is-warning">
<Link href={`/post/edit/${post._id}`}>
<a> Update Post </a>
</Link>
</span>
<button
onClick={this.deleteConfirmed}
className="button is-raised is-danger"
>
Delete Post
</button>
</div>
</div>
)}
</div>
<div>
<h4 className="raw"> Description: </h4>
<p className="column">{post.body}</p>
</div>
<br />
</div>
);
};
render() {
console.log("Render Quota:", this.props.postId, this.state.ispost);
const { postId } = this.props;
const {
post,
redirectToHome,
redirectToSignin,
redirectToBack
} = this.state;
if (redirectToHome) {
Router.push("/");
} else if (redirectToSignin) {
Router.push("/signin");
} else if (redirectToBack) {
Router.back();
}
return (
<section className="section">
<div className="container">
<h2 className="title">{post.title}</h2>
{!post ? (
<div className="hero">
<h2>Loading...</h2>
</div>
) : (
this.renderPost(post)
)}
</div>
</section>
);
}
}
export default SinglePost;
答案 0 :(得分:0)
已解决更新 在AyèchHamza建议之后,添加了getInitialProps方法,这就是所需要的。 因此,在[postid] .js中,
import React from "react";
import Layout from "../../components/layout";
import SinglePost from "../../components/post/singlePost";
Post.getInitialProps = async ctx => {
const PostId = ctx.query.postid;
return { PostId };
};
function Post({ PostId }) {
return (
<Layout>
<SinglePost PostId={PostId}/>
</Layout>
);
}
export default Post;
和SinglePost.js中
componentDidMount() {
const postId = this.props.PostId;
singlePost(postId).then(data => {
if (data.error) {
console.log(data.error);
} else {
this.setState({
post: data,
likes: data.likes.length,
like: this.checkLike(data.likes),
comments: data.comments
});
}
});
}