【问题标题】:React component : setState worked but didnt update componentReact 组件:setState 工作但没有更新组件
【发布时间】:2021-01-12 06:30:46
【问题描述】:

抱歉,我是 React 新手。我正在尝试建立一个基本的社交网络来学习反应。 语境: 当我点击“like”按钮时,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>
            )
    }
}

新闻源组件:

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"))

【问题讨论】:

  • 将 setState 与回调函数一起使用。 this.setState((state) => {...state, isLoaded: true});

标签: javascript reactjs components


【解决方案1】:

试试这样的:

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'));

【讨论】:

    【解决方案2】:

    看起来你已经颠倒了你的逻辑,即你的按钮直接更新后端的数据,但没有更新组件状态,所以 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>
    

    【讨论】:

    • 非常感谢,现在可以使用了!我不确定 this.setState( prevState =&gt; ({ liked: !prevState.liked }) 是什么?我想它适用于this.setState({ liked: false },但我不太明白如何。提前致谢!
    • @michael_vincent 它只是切换布尔值,即!true -&gt; false!false -&gt; true
    猜你喜欢
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    相关资源
    最近更新 更多