【问题标题】:Rails and ReactJS - Re-rendering componentRails 和 ReactJS - 重新渲染组件
【发布时间】:2015-10-25 01:55:38
【问题描述】:

所以我仍在使用 Todo 应用程序来学习 Reactjs。 该应用程序很简单,用户可以添加新任务并将其标记为已完成。

我正在使用 react-rails gem 在后端使用 Rails,并尝试了不同的方法来在创建或刚刚更新新任务时处理组件重新渲染。

每次创建或更新新任务时,我都会从后端渲染包含所有任务的 JSON,而不是按给定的时间间隔从服务器获取数据。

我想知道这是否是最优化的方法。 所以这是我的 Rails 控制器:

class TasksController < ApplicationController
	before_filter :get_tasks

	def get_tasks
		@tasks = Task.where('iscompleted is null').order(created_at: :desc)
	end

	def index
		render :json => @tasks
	end

	def create
		@task = Task.create(task_params)

		render :json => @tasks
	end

	def update
		@task = Task.update(params[:id], task_params)

		render :json => @tasks
	end



	private
	def task_params
		params.require(:task).permit(:id, :name, :iscompleted)
	end
end

这是我的 ReactJS 组件:

var TodoBox = React.createClass({

	loadTasksFromServer: function() {
		$.ajax({
			url: this.props.url,
			dataType: 'json',
			cache: false,
			success: function(data) {
				this.setState({data: data.tasks});
			}.bind(this)
		});
	},
	handleTaskSubmit: function(task) {
		$.ajax({
			url: this.props.url,
			dataType: 'json',
			type: 'POST',
			data: {task},
			success: function(data) {
				this.setState({data: data.tasks});
			}.bind(this),
			error: function(xhr, status, err) {
				console.error(this.props.url, status, err.toString());
			}.bind(this)
		});		
	},
	handleTaskCompleted: function(task) {
		$.ajax({
			url: '/task/' + task.id,
			dataType: 'json',
			type: 'PATCH',
			data: {task},
			success: function(data) {
				this.setState({data: data.tasks});
			}.bind(this),
			error: function(xhr, status, err) {
				console.error(this.props.url, status, err.toString());
			}.bind(this)
		});
		
	},
	getInitialState: function() {
		return {
			data: []
		};
	},
	componentDidMount: function() {
		this.loadTasksFromServer();
	},
	render: function() {
		return (
			<div className="todoBox">
			<div className="container-fluid col-md-6 col-md-offset-3">
			<TodoForm onTaskSubmit={this.handleTaskSubmit}/>
			<TodoList onTaskCompleted={this.handleTaskCompleted} data={this.state.data}/>
			
			</div>
			
			</div>
			);
	}
});

这种方法效果很好,但我是来学习的,所以每条评论或建议都会非常感激。

谢谢

【问题讨论】:

  • 我投票结束这个问题,因为关于重构工作代码的问题更适合codereview.stackexchange.com
  • 那么您的问题是:“仅重新渲染所有任务而不是确定已添加/删除/更新哪个任务以调用渲染是否是正确的方法?”如果这是问题所在,那么这是使用 ReactJS 的正确方法。 React 运行一个虚拟 dom diff 算法来最小化 Dom 操作,这是昂贵的部分
  • @NaturalLam 感谢您的回答。所以基本上,如果我想重新渲染所有任务,这是正确的方法。但是,确定添加/更新了哪个任务的正确方法是什么?有没有办法不重新渲染所有任务?谢谢

标签: javascript ruby-on-rails reactjs


【解决方案1】:

我发现在 React 中过滤结果更有效,因为它不需要从后端重新渲染所有任务。 因此,我只从 rails 后端渲染新对象或更新的对象,如下所示:

class TasksController < ApplicationController

def index
    @tasks = Task.all
    render :json => @tasks
end

def create
    @task = Task.create(task_params)

    render :json => @task
end

def update
    @task = Task.update(params[:id], task_params)

    render :json => @task
end



private
def task_params
    params.require(:task).permit(:id, :name, :iscompleted)
end

因此 React 组件看起来像这样:

var TodoBox = React.createClass({

loadTasksFromServer: function() {
    var rawData = [];
    $.ajax({
        url: this.props.url,
        dataType: 'json',
        cache: false,
        success: function(data) {
            this.setState({data: data.tasks});
        }.bind(this)
    });
},


handleTaskSubmit: function(task) {
    $.ajax({
        url: this.props.url,
        dataType: 'json',
        type: 'POST',
        data: {task},
        success: function(data) {
            this.state.data.push(data.task);
            this.setState({data: this.state.data});
        }.bind(this),
        error: function(xhr, status, err) {
            console.error(this.props.url, status, err.toString());
        }.bind(this)
    });     
},
handleTaskCompleted: function(task) {
    $.ajax({
        url: '/task/' + task.id,
        dataType: 'json',
        type: 'PATCH',
        data: {task},
        success: function(data) {
            task.iscompleted = data.task.iscompleted;
            this.setState({data: this.state.data});
        }.bind(this),
        error: function(xhr, status, err) {
            console.error(this.props.url, status, err.toString());
        }.bind(this)
    });

},
getInitialState: function() {
    return {
        data: []
    };
},
componentDidMount: function() {
    this.loadTasksFromServer();
},
render: function() {
    return (
        <div className="todoBox">
        <div className="container-fluid col-md-6 col-md-offset-3">
        <TodoForm onTaskSubmit={this.handleTaskSubmit}/>
        <TodoList onTaskCompleted={this.handleTaskCompleted} data={this.state.data}/>

        </div>

        </div>
        );
}

});

然后我在显示之前过滤 TodoList 组件中的结果。

【讨论】:

    猜你喜欢
    • 2023-04-11
    • 2020-06-20
    • 2019-01-01
    • 2018-09-01
    • 1970-01-01
    • 2022-11-25
    • 2021-12-06
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多