【问题标题】:react-rails : component does not re-render after record createdreact-rails :创建记录后组件不会重新渲染
【发布时间】:2016-10-06 08:24:07
【问题描述】:

在学习教程时,我试图在通过 AJAX 调用创建新记录(游戏)后重新渲染我的 GamesBox。

记录被保存,我可以通过刷新看到它,但这似乎不是 React 方式...

容器:

var GamesBox = React.createClass ({

  getInitialState: function(){
    return {
      game: this.props.games
    }
  },

  parentGameSubmit (formData){

    $.ajax({
      url: "/games",
      dataType: 'json',
      type: 'POST',
      data: formData,

      success: function(games) {

        this.setState({games: games});

      }.bind(this),

      error: function(response, status, err) {

        console.log(this.props.url, status, err.toString())
      }.bind(this)


    });
  },

    render () {
      return (
        <div>
        <h1> Hey everyone </h1>
        
        <Game games={this.state.game} />

        <GameForm parentGameSubmit={this.parentGameSubmit}/>
        </div>
      );
    }
});

呈现的游戏列表:

var Game = React.createClass({

 renderProjectRows: function(){
    return(
      this.props.games.map(function(game){
        return(
          <div className="row" style={{marginTop: "20px"}} key={game.id}>

            <div className="col-sm-2">
              <h2 className="text-center" key={game.id}><a href={"/games/" + game.id}> {game.name} </a></h2>
            </div>

          </div>
        )
      })
    );
  },

  render: function() {
    return(
      <div>

        <div className="row" style={{marginTop: "50px"}}>

          <div className="col-sm-2">
          </div>

          <div className="col-sm-2" style={{fontWeight: "bold"}}>
            Name
          </div>

        </div>

        {this.renderProjectRows()}

      </div>
    );
  }

});

表格:

var GameForm = React.createClass({

  getInitialState: function(){
    return {name: ""};
  },

  resetState: function(){
    this.setState({name: ""});
  },

  newGameSubmit: function(e){
    e.preventDefault();

   this.props.parentGameSubmit({game: {name: this.state.name, white_castling: this.state.white_castling, black_castling: this.state.black_castling}},
    this.resetState);
   this.setState({name: ''});
  },

  handleNameChange: function(e){
    this.setState({name: e.target.value});
  },


  renderGameNameField: function(){


    return(

      <div className='row'>

        <div className='col-sm-4'>

          <div className= 'form-group'>

            <input
              name="game[name]"
              type="string"
              placeholder="Game name"
              value={this.state.name}
              onChange={this.handleNameChange}
              className="string form-control"
            />

          </div>

        </div>

      </div>
    );
  },



  render: function() {

    return(
      <div>
        <h4 style={{marginTop: "50px"}}> Create New Game </h4>

        <form style={{marginTop: "30px"}} onSubmit={this.newGameSubmit}>

          <div className='form-inputs'/>


            {this.renderGameNameField()}
            


            <div className='row'>
              <div className='col-sm-4'>
                <input type="submit" value="Save" className='btn btn-primary' />
              </div>
            </div>

        </form>

      </div>

    );
  }
});

游戏控制器:

class GamesController < ApplicationController
  before_action :authenticate_user!

  def index
    @game = Game.all
  end

  def new
    @game = Game.new
  end

  def create
    @game = Game.new(game_params)
     respond_to do |format|
    if @game.save
      @game.update(white_user_id: current_user[:id])
      format.html { redirect_to @game, notice: 'Project was successfully created.' }

      format.json { render json: Game.all.order(:name)}
    else
      format.html {render :new}
    end
  end
  end
                                             
   private

  def game_params
    params.require(:game).permit(:name, :white_castling, :black_castling)
    end
  end
     

请给我一些见解

【问题讨论】:

    标签: javascript ruby-on-rails ajax reactjs react-rails


    【解决方案1】:
    1. 你在游戏和游戏之间不断地交换。即 game: this.props.games 在您的 GameBox 组件中。如果它是一个数组,你应该使用游戏。 (我假设这是真的,因为您在 Game 组件中使用了 map 函数)。
    2. 您是在发送成功的 ajax 时更新游戏状态,而不是您实际使用的游戏状态。

    如果你想要一个超级快速的修复,你可以在你的 parentGameSubmit 函数中将 this.setState({games: games}); 更改为 this.setState({game: games});。

    【讨论】:

      【解决方案2】:

      一切看起来都不错,除了你的表格。当您在事件处理程序中时范围发生变化,您必须绑定您的上下文。

      onChange={this.handleNameChange.bind(this)}

      和

      onSubmit={this.newGameSubmit.bind(this)}

      试试这个:

      var GameForm = React.createClass({
      
        getInitialState: function(){
          return {name: ""};
        },
      
        resetState: function(){
          this.setState({name: ""});
        },
      
        newGameSubmit: function(e){
          e.preventDefault();
      
         this.props.parentGameSubmit({game: {name: this.state.name, white_castling: this.state.white_castling, black_castling: this.state.black_castling}},
          this.resetState);
         this.setState({name: ''});
        },
      
        handleNameChange: function(e){
          this.setState({name: e.target.value});
        },
      
      
        renderGameNameField: function(){
      
      
          return(
      
            <div className='row'>
      
              <div className='col-sm-4'>
      
                <div className= 'form-group'>
      
                  <input
                    name="game[name]"
                    type="string"
                    placeholder="Game name"
                    value={this.state.name}
                    onChange={this.handleNameChange.bind(this)}
                    className="string form-control"
                  />
      
                </div>
      
              </div>
      
            </div>
          );
        },
      
      
      
        render: function() {
      
          return(
            <div>
              <h4 style={{marginTop: "50px"}}> Create New Game </h4>
      
              <form style={{marginTop: "30px"}} onSubmit={this.newGameSubmit.bind(this)}>
      
                <div className='form-inputs'/>
      
      
                  {this.renderGameNameField()}
                  
      
      
                  <div className='row'>
                    <div className='col-sm-4'>
                      <input type="submit" value="Save" className='btn btn-primary' />
                    </div>
                  </div>
      
              </form>
      
            </div>
      
          );
        }
      });

      【讨论】:

      • React.createClass 已经自动绑定了所有函数,onChange={this.handleNameChange.bind(this)} 和 onSubmit={this.newGameSubmit.bind(this)} 不会有任何改变。
      猜你喜欢
      • 2023-03-13
      • 2021-05-19
      • 2022-01-26
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      相关资源
      最近更新 更多