Не могу использовать Next js Queryparams реквизиты внутри componentDidMount () - PullRequest
0 голосов
/ 23 января 2020

Я использую Next. js и реагирую на эту проблему в течение нескольких дней. Так что в Next. js страниц у меня есть Dynami c page [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? Или есть какой-то другой способ, я должен подойти к этой проблеме? также вот мой полный единственный пост. 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>{" "}
        &nbsp;
        <span className="button is-primary" onClick={() => Router.back()}>
          <strong> Back to posts </strong>
        </span>
        &nbsp;
        {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>
              &nbsp;
              <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>
                &nbsp;
                <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; 

1 Ответ

0 голосов
/ 24 января 2020

ОБНОВЛЕНИЕ - РЕШЕНО После предложения Айеха Хамзы добавлен метод 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
        });
      }
    });
  }
...