Reactjs 在componentDidMount中响应API调用,componentWillReceiveProps(订单混乱)

Reactjs 在componentDidMount中响应API调用,componentWillReceiveProps(订单混乱),reactjs,react-redux,axios,Reactjs,React Redux,Axios,我对反应和重复是相当陌生的。我遇到了这个问题,当我刷新页面时,收视率有时不会显示出来(请参见屏幕截图)。我认为这是因为有时候Redux的用户在执行loadTeamsData之前进入Component将收到props,但我不知道为什么这会导致评分不显示。(另外,我觉得我的代码是垃圾……任何批评家都会受到赞赏!) Home.js export class Home extends React.Component { state = { upVote: null, downVot

我对反应和重复是相当陌生的。我遇到了这个问题,当我刷新页面时,收视率有时不会显示出来(请参见屏幕截图)。我认为这是因为有时候Redux的用户在执行
loadTeamsData
之前进入
Component将收到props
,但我不知道为什么这会导致评分不显示。(另外,我觉得我的代码是垃圾……任何批评家都会受到赞赏!)

Home.js

export class Home extends React.Component {

  state = {
    upVote: null,
    downVote: null,
    clickedTeam: "",
    teams: teams
  };

  // When component mounted, add in thumbUp & thumbDown properties to each team
  componentDidMount() {
    const { user } = this.props.auth;
    console.log("didmount");

    this.loadTeamsData();

    // Stores user voting info to state when coming from a different page
    if (user) {
      if (!(Object.entries(user).length === 0)) {
        console.log("user", user, user.upVote, user.downVote);
        this.setState({
          upVote: user.upVote,
          downVote: user.downVote
        });
      }
    }
  }

  // Loads teams thumbUp, thumbDown data to state
  loadTeamsData = () => {
    axios.get("/api/teams/").then(res => {
      console.log("data", res.data);
      this.setState({
        teams: this.state.teams.map(team => {
          res.data.map(vote => {
            if (vote.id === team.id) {
              team.thumbUp = vote.thumbUp;
              team.thumbDown = vote.thumbDown;
            }
            return vote;
          });
          return team;
        })
      });
    });
  };

  // When props from Redux come in, set the state
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { user } = nextProps.auth;

    if (user !== this.props.auth.user && user) {
      console.log("willreceiveprops", `\n`, this.props.auth.user, user);
      this.setState({
        upVote: user.upVote,
        downVote: user.downVote
      });
    }
  }

  // Handle click on thumbs
  onClickHandler = (id, e) => {
    const { alert } = this.props;
    const up = e.target.classList.contains("up");

    if (this.props.auth.isAuthenticated) {
      if (up && this.state.upVote === "") {
        if (id === this.state.downVote) {
          alert.error("You cannot up vote and down vote the same team!");
        } else {
          this.props.update_up(id);
          this.setState(prevState => {
            return {
              teams: prevState.teams.map(team => {
                if (id === team.id) {
                  team.thumbUp = team.thumbUp + 1;
                  team.votedUpColor = { color: "#1E95E0" };
                }
                return team;
              }),
              clickedTeam: id,
              upVote: id
            };
          });
          alert.show(`You Up Voted ${id}`);
        }
      } else if (!up && this.state.downVote === "") {
        if (id === this.state.upVote) {
          alert.error("You cannot up vote and down vote the same team!");
        } else {
          this.props.update_down(id);
          this.setState(prevState => {
            return {
              teams: prevState.teams.map(team => {
                if (id === team.id) {
                  team.thumbDown = team.thumbDown + 1;
                  team.votedDownColor = { color: "#F8004C" };
                }
                return team;
              }),
              clickedTeam: id,
              downVote: id
            };
          });
          alert.show(`You Down Voted ${id}`);
        }
      } else {
        alert.show("You have already voted.");
      }
    } else {
      alert.show("Please log in first!");
      this.props.history.push(`/login`);
    }
  };

  // When user votes, update the db before updating the state
  UNSAFE_componentWillUpdate(newProps, newState) {
    newState.teams.map(team => {
      if (team.id === newState.clickedTeam) {
        axios.put(`/api/teams/${newState.clickedTeam}/`, {
          id: team.id,
          thumbUp: team.thumbUp,
          thumbDown: team.thumbDown
        });
      }
    });
  }

  render() {
    // Welcome header message when user logs in
    console.log("render", this.state.teams[0].thumbUp);
    const { isAuthenticated, user } = this.props.auth;
    const { upVote, downVote } = this.state;
    const welcome_header = (
      <div className="welcome-header">
        <h4 style={{ textAlign: "left" }} className="welcome-header-line">
          Welcome, {user && user.username}!
        </h4>
        <h4 style={{ textAlign: "left" }} className="welcome-header-line">
          <span>
            Your Vote:{" "}
            <i className="far fa-thumbs-up up" style={{ color: "#1E95E0" }}></i>
            <span style={{ textTransform: "capitalize" }}>{upVote}</span>
          </span>{" "}
          <span>
            <i
              className="far fa-thumbs-down down"
              style={{ color: "#F8004C" }}
            ></i>
            <span style={{ textTransform: "capitalize" }}>{downVote}</span>
          </span>
        </h4>
      </div>
    );

    return (
      <div className="home">
        <div className="home-container">
          {isAuthenticated && welcome_header}
          <h2>Who Is Your NBA Champion This Year?</h2>
          <Teams
            upVote={this.state.upVote}
            downVote={this.state.downVote}
            teams={this.state.teams}
            onClickHandler={this.onClickHandler}
          />
        </div>
      </div>
    );
  }
}

Home.propTypes = {
  update_up: PropTypes.func.isRequired,
  update_down: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps, { update_up, update_down })(
  withAlert()(withRouter(Home))
);
导出类Home扩展React.Component{
状态={
向上投票:无效,
否决票:无效,
单击团队:“”,
团队:团队
};
//安装组件时,将“拇指向上”和“拇指向下”属性添加到每个团队
componentDidMount(){
const{user}=this.props.auth;
console.log(“didmount”);
这个.loadTeamsData();
//当来自不同页面时,将用户投票信息存储到状态
如果(用户){
if(!(Object.entries(user.length==0)){
console.log(“user”,user,user.upVote,user.downVote);
这是我的国家({
upVote:user.upVote,
downVote:user.downVote
});
}
}
}
//将团队上下数据加载到状态
loadTeamsData=()=>{
get(“/api/teams/”)。然后(res=>{
console.log(“数据”,res.data);
这是我的国家({
团队:this.state.teams.map(团队=>{
res.data.map(投票=>{
if(vote.id==team.id){
team.thumbUp=vote.thumbUp;
team.thumbDown=vote.thumbDown;
}
返回投票;
});
返回队;
})
});
});
};
//当Redux提供道具时,设置状态
不安全组件将接收道具(下一步){
const{user}=nextrops.auth;
if(user!==this.props.auth.user&&user){
log(“willreceiveprops”,`\n`,this.props.auth.user,user);
这是我的国家({
upVote:user.upVote,
downVote:user.downVote
});
}
}
//用拇指点击手柄
onClickHandler=(id,e)=>{
const{alert}=this.props;
const up=e.target.classList.contains(“up”);
if(this.props.auth.isAuthenticated){
if(up&&this.state.upVote==“”){
if(id==this.state.downVote){
警告。错误(“您不能对同一团队进行向上投票和向下投票!”);
}否则{
此.props.update\u up(id);
this.setState(prevState=>{
返回{
团队:prevState.teams.map(团队=>{
if(id==team.id){
team.thumbUp=team.thumbUp+1;
team.votedUpColor={color:#1E95E0};
}
返回队;
}),
单击团队:id,
向上投票:id
};
});
alert.show(`youup-Voted${id}`);
}
}如果(!up&&this.state.downVote==“”),则为else{
if(id==this.state.upVote){
警告。错误(“您不能对同一团队进行向上投票和向下投票!”);
}否则{
this.props.update_down(id);
this.setState(prevState=>{
返回{
团队:prevState.teams.map(团队=>{
if(id==team.id){
team.thumbDown=team.thumbDown+1;
team.votedDownColor={color:#F8004C};
}
返回队;
}),
单击团队:id,
否决票:id
};
});
alert.show(`youdown-Voted${id}`);
}
}否则{
显示(“你已经投票了。”);
}
}否则{
警报。显示(“请先登录!”);
this.props.history.push(`/login`);
}
};
//当用户投票时,在更新状态之前更新数据库
不安全组件将更新(newProps、newState){
newState.teams.map(团队=>{
if(team.id==newState.clickedTeam){
axios.put(`/api/teams/${newState.clickedTeam}/`{
id:team.id,
大拇指:团队,大拇指,
大拇指朝下:团队,大拇指朝下
});
}
});
}
render(){
//用户登录时的欢迎标头消息
console.log(“render”,this.state.teams[0].thumbUp);
const{isAuthenticated,user}=this.props.auth;
const{upVote,downVote}=this.state;
const welcome_头=(
欢迎,{user&&user.username}!
您的投票:{“}
{upVote}
{" "}
{否决票}
);
返回(
{isAuthenticated&&welcome_头}
谁是你今年的NBA冠军?
);
}
}
Home.propTypes={
需要更新:PropTypes.func.isRequired,
更新_down:PropTypes.func.isRequired,
auth:PropTypes.object.isRequired
};
常量mapStateToProps=状态=>({
auth:state.auth
});
导出默认连接(MapStateTops,{update\u up,update\u down})(
withAlert()(withRouter(Home))
);
当收视率显示时

收视率未显示时

我正在控制台上记录渲染方法中的
this.state.teams[0]
this.state.teams[0].thumbUp
。 即使在第一次渲染期间,thumbUp和thumbDown都会显示在
this.state.teams[0]
中,但是
this.state.teams[0]。thumbUp
似乎未定义


我碰巧解决了这个问题。问题实际上在Rating.js文件中,很抱歉我没有发布该文件,因为我认为问题应该在Home.js中

之前,在Rating.js文件中,我最初从redux引入了用户,这导致了问题(我相信在Home.js中,
axios get
调用发生在
组件将接收props
之后,并没有使评级重新呈现)

之后,而不是
import React from "react";
import "./Rating.css";
import PropTypes from "prop-types";
import { connect } from "react-redux";

const Rating = props => {
  const { thumbUp, thumbDown, id, votedUpColor, votedDownColor } = props.team;
  const { upVote, downVote, onClickHandler } = props;
  const { user } = props.auth;

  let thumbUpColor =
    user && id === upVote ? { color: "#1E95E0" } : votedUpColor;
  let thumbDownColor =
    user && id === downVote ? { color: "#F8004C" } : votedDownColor;

  console.log(id, thumbUp, thumbDown);
  return (
    <div className="rating" key={id}>
      <button
        className="thumb-up up"
        style={thumbUpColor}
        onClick={e => onClickHandler(id, e)}
      >
        <i className="far fa-thumbs-up up"></i>
        <span style={{ userSelect: "none" }} className="up">
          {thumbUp}
        </span>
      </button>
      <button
        className="thumb-down down"
        style={thumbDownColor}
        onClick={e => onClickHandler(id, e)}
      >
        <i className="far fa-thumbs-down down"></i>
        <span style={{ userSelect: "none" }} className="down">
          {thumbDown}
        </span>
      </button>
    </div>
  );
};

Rating.propTypes = {
  team: PropTypes.object.isRequired,
  onClickHandler: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps)(Rating);
import React from "react";
import "./Rating.css";
import PropTypes from "prop-types";
// import { connect } from "react-redux";

const Rating = props => {
  const { thumbUp, thumbDown, id, votedUpColor, votedDownColor } = props.team;
  const { upVote, downVote, onClickHandler, user } = props;
  // const { user } = props.auth;

  let thumbUpColor =
    user && id === upVote ? { color: "#1E95E0" } : votedUpColor;
  let thumbDownColor =
    user && id === downVote ? { color: "#F8004C" } : votedDownColor;

  console.log(id, thumbUp, thumbDown);
  return (
    <div className="rating" key={id}>
      <button
        className="thumb-up up"
        style={thumbUpColor}
        onClick={e => onClickHandler(id, e)}
      >
        <i className="far fa-thumbs-up up"></i>
        <span style={{ userSelect: "none" }} className="up">
          {thumbUp}
        </span>
      </button>
      <button
        className="thumb-down down"
        style={thumbDownColor}
        onClick={e => onClickHandler(id, e)}
      >
        <i className="far fa-thumbs-down down"></i>
        <span style={{ userSelect: "none" }} className="down">
          {thumbDown}
        </span>
      </button>
    </div>
  );
};

Rating.propTypes = {
  team: PropTypes.object.isRequired,
  onClickHandler: PropTypes.func.isRequired
  // auth: PropTypes.object.isRequired
};

// const mapStateToProps = state => ({
//   auth: state.auth
// });

export default Rating;