【问题标题】:Looping dynamic server response in React render在 React 渲染中循环动态服务器响应
【发布时间】:2017-09-14 23:27:48
【问题描述】:

我正在用 React 开发一些 SPA,我多次遇到过这个问题;我最终以丑陋的方式解决了它,就像下面代码中发布的那样。

我觉得我遗漏了一些明显的东西,但我真的想不出更优雅(甚至正确)的方法来实现相同的结果,你能帮我吗?

class Leaderboard extends React.Component {
  constructor(props) {
    super(props);
    this.state={
      lb:{},
      leaderboard:""
    };
    this.leaderboardGet = this.leaderboardGet.bind(this);
    this.leaderboardSet = this.leaderboardSet.bind(this);
    this.lblooper = this.lblooper.bind(this);
    this.lbconstruct = this.lbconstruct.bind(this);
  }


  leaderboardGet(callback){ //server call which returns data
    axiosCall.get('leaderboard.php',{params:{user:this.props.user}})
    .then((response)=>{
      var arr=response.data;
      callback(arr);
    })
    .catch((error)=>{
      console.log(error);
    })
  }
  leaderboardSet(a){ //puts in lb object the results of the server call and calls lb looper
    this.setState({lb: a});
    this.lblooper();
  }
  componentWillMount(){
    this.leaderboardGet(this.leaderboardSet);
  }

  lblooper(){ //the ugliness itself: loops the data in lb object, and pushes it into an "html string" in lblconstruct function 
    Object.entries(this.state.lb).forEach(
      ([key, value]) => this.lbconstruct(`<div class="leaderblock ${value.active}"><div class="leaderscore">${value.pos}) </div><div class="leadername">${value.usrname}</div><div class="leaderscore dx">${value.pts} <i class='fa fa-trophy'></i></div></div>`)
    );
  }
  lbconstruct(s){
    this.setState({leaderboard:this.state.leaderboard+=s});
  }

  render() {
    return (
      <div>
        <div className="leaderboard">
          <div dangerouslySetInnerHTML={{__html:this.state.leaderboard}}/>
        </div>
      </div>
    );
  }
}

基本上,如果我有服务器数据必须放入 html 格式的 N 循环中,我找不到其他方法,所以我想知道我错在哪里。

【问题讨论】:

    标签: javascript reactjs promise axios


    【解决方案1】:

    将数据输出到渲染函数中的反应元素中:

    class Leaderboard extends React.Component {
      constructor(props) {
        super(props);
        this.state={
          leaderboard: {},
        };
      }
    
      componentWillMount(){
        axiosCall.get('leaderboard.php', { params: { user:this.props.user } })
          .then(response => this.setState({ leaderboard: response.data }))
          .catch(console.log)
      }
    
      render() {
        const { leaderboard } = this.state
        return (
          <div>
            <div className="leaderboard">
              // .map returns a new array, which we have populated with the react elements
              { Object.keys(leaderboard).map((key) => {
                const value = leaderboard[key]
                return (
                  <div key={key} class={`leaderblock ${value.active}`}>
                    <div class="leaderscore">{value.pos}</div>
                    <div class="leadername">{value.usrname}</div>
                    <div class="leaderscore dx">
                      {value.pts}
                      <i class='fa fa-trophy'></i>
                    </div>
                  </div>
                )
              }) }
            </div>
          </div>
        );
      }
    }
    

    这样做是为了让 react 起作用,它可以跟踪那里有哪些元素,如果你添加一个,它可以看到差异,只需将一个元素添加到末尾,而不是重新渲染一切。

    另请注意,如果您只获取一次数据,则使用“容器”组件获取数据并将其作为道具传递给您的“哑”组件可能是有意义的。

    【讨论】:

    • .map((key,value)=&gt; ...) 是错误的。 .map((key,index)=&gt; ...) 是正确的。您需要const value = this.state.leaderboard[key] 或类似名称。
    猜你喜欢
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 2015-05-07
    • 2020-06-29
    • 2019-10-05
    • 1970-01-01
    相关资源
    最近更新 更多