反应组件:setState工作,但没有更新组件

时间:2020-09-25 23:00:18

标签: javascript reactjs components

对不起,我是React的新手。我正在尝试建立一个基本的社交网络来学习反应。 内容: 当我单击“喜欢”按钮时,setState应该调用该函数以更新组件的状态,但是仅当刷新页面时才会更新。我认为ComponentDidUpdate函数的调用不应该如此。我做错了什么?感谢您的帮助!

下面是代码的一部分:

类似于按钮组件:

class Like_Button extends React.Component {

  constructor(props) {
    super(props);
    this.state = {liked : "Like"};
  }

  isliked(){
    fetch("likes_of_user/")
    .then(res => res.json())
    .then((result) => {
        result.map(x => {if(this.props.pk == x.liked_post){this.setState({liked: "Unlike"});}});
    })
  }

  componentDidMount() {
    this.isliked();
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevState.liked !== this.state.liked) {
    this.isliked();
  }
}

  render() {
        return (
                <button className = "buttons" onClick={() => {
                var csrftoken = getCookie('csrftoken');
                fetch(`like_post/${this.props.pk}`, {method: "POST", headers: {'Accept': 'application/json', 'Content-Type': 'application/json','X-CSRFToken': csrftoken}})
                }}>{this.state.liked}</button>
            )
    }
}

Newsfeed组件:

class Newsfeed_comp extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };
  }

  componentDidMount() {
    fetch("get_newsfeed/")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result
          });
        },
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map((item ,index) => (
            <li className="postbox" key={`${item}${index}`}>
              {item.author}
              {item.date}
              {item.content}
              <Like_Button pk={item.id} />
            </li>
          ))}
        </ul>

      );
    }
  }
}

ReactDom渲染:

ReactDOM.render(<Newsfeed_comp />, document.getElementById("newsfeed_view"))

2 个答案:

答案 0 :(得分:2)

尝试这样的事情:

LikeButton.js

import React, { useEffect, useState } from 'react';

export default function LikeButton({ pk }) {
  const [like, setLike] = useState(false);

  useEffect(() => {
    const fetchLike = async () => {
      const res = await fetch("likes_of_user/");
      const result = await res.json();

      if (result.length > 0) {
        setLike(result.find(item => item.liked_post === pk));
      }
    };

    try {
      fetchLike();
    } catch (error) {
      // handle error
    }
  });

  const handleClick = async () => {
    const csrftoken = getCookie('csrftoken');

    return fetch(`like_post/${pk}`, {
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'X-CSRFToken': csrftoken
      },
      method: 'POST',
    });
  };

  return (
    <button className='buttons' onClick={handleClick}>
      {like}
    </button>
  );
};

NewsFeed.js

import React, { useEffect, useState } from 'react';

export function NewsFeed() {
  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [items, setItems] = useState([]);

  useEffect(() => {
    const getNewsFeed = async () => {
      const res = await fetch('get_newsfeed/');
      const result = await res.json();

      setIsLoaded(true);
      setItems(result);
    };

    try {
      getNewsFeed();
    } catch (error) {
      setIsLoaded(true);
      setError(error);
    }
  });

  if (error) return <div>Error: {error.message}</div>;
  if (isLoaded) return <div>Loading...</div>;

  const list = items.map((item) => (
    <li className='postbox' key={item.content}>
      {item.author}
      {item.date}
      {item.content}
      <LikeButton pk={item.id} />
    </li>
  ));

  return <ul>{list}</ul>;
};

App.js

ReactDOM.render(<NewsFeed />, document.getElementById('newsfeed_view'));

答案 1 :(得分:1)

看起来您已经颠倒了逻辑,也就是说,您的按钮直接更新了后端中的数据,但是没有更新组件状态,因此componentDidUpdate并不像您看到的那样被调用。需要刷新,以便重新安装组件,并且componentDidMount可以获取喜欢的数据。

请尝试先更新本地状态,然后使用componentDidUpdate发出更新后端的副作用。

constructor(props) {
  super(props);
  this.state = { liked: true };
}

isliked() {
  fetch("likes_of_user/")
    .then(res => res.json())
    .then((result) => {
      result.map(x => {
        if (this.props.pk === x.liked_post) {
          this.setState({ liked: false });
        }
      });
  })
}

componentDidUpdate(prevProps, prevState) {
  if (prevState.liked !== this.state.liked) {
    const csrftoken = getCookie('csrftoken');
    fetch(
      `like_post/${this.props.pk}`,
       {
         method: "POST",
         headers: {
           'Accept': 'application/json',
           'Content-Type': 'application/json',
           'X-CSRFToken': csrftoken,
         },
       }
    );
  }
}

<button
  className="buttons"
  onClick={() => this.setState(
    prevState => ({ liked: !prevState.liked })
  )}
>
  {this.state.liked ? "Liked" : "Unliked"}
</button>