Rails和ReactJS - 重新渲染组件

时间:2021-05-02 19:13:06

So i'm still playing with a Todo application in order to learn Reactjs. The application is quit simple, a user can add a new task and mark it as completed.

所以我还在玩Todo应用程序以学习Reactjs。应用程序退出简单,用户可以添加新任务并将其标记为已完成。

I'm using Rails on the backend using the react-rails gem and tried differents approach to handle component re-rendering when a new task is created or just updated.

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

Instead of fetching the data from the server at a given interval, i'm rendering a JSON with all the tasks from the backend everytime a new task is created or updated.

每次创建或更新新任务时,我都不是以给定的间隔从服务器获取数据,而是使用后端的所有任务呈现JSON。

I was wondering if this is the most optimized approched. So here's my Rails controller :

我想知道这是否是最优化的方法。所以这是我的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

and here's my ReactJS component :

这是我的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>
			);
	}
});

This method is working very well but i'm here to learn so every comment or advice will be much appreciated.

这种方法工作得很好,但我在这里学习,所以每个评论或建议将不胜感激。

Thanks

1 个解决方案

#1


0  

I found that filtering the results in React is more effective since it down't require to rerender all the tasks from the backend. Therefore, i'm only rendering the new object or the updated object from rails backend as follow :

我发现在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

And therefore the React component looks like this :

因此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>
        );
}

});

Then i'm filtering the results in the TodoList component before displaying them.

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

#1


0  

I found that filtering the results in React is more effective since it down't require to rerender all the tasks from the backend. Therefore, i'm only rendering the new object or the updated object from rails backend as follow :

我发现在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

And therefore the React component looks like this :

因此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>
        );
}

});

Then i'm filtering the results in the TodoList component before displaying them.

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