git clone [email protected]:madmaniak/react-kis-rails.git
cd react-kis-rails
bundle
npm install
rails s
Checkout localhost:3000. Read commits.
-
Everything (except Backbone.Events) is a component even Router.
-
There is only one state of particular data. Therefore there is no need to synchronize data over the application. You can find component proper for state by LCE.
-
There is no models or collections but pure data in
state
. -
Directories tree reflects virtual DOM structure of the app. Keep reusable components (e.g. UI components) outside this tree in
components
directory. -
Always emit event when action occurs and let it be handled by state component. Distinguish action handlers for local ones and ones talking with API.
-
Each state component talking with API has it's own API endpoints. Lets call such component an ASC - Api State Component.
-
Don't do REST. We don't have models and collections. Distinguish reading from writing actions and keep it in sepparate flows.
Life cycle of ASC:
- after mounting component get state from API
- if action occurs
- remember old state
- set expected result to state basing on passed params
- post action with params and callback state url to the API
- [API] set new state basing on action and params
- [API] redirect to callback state url and return current state of ASC
- if action fails
- bring back old state
- Don't map routings manually. Ask proper serializers or actions basing on get/post and url.
- Each ASC has it's own Serializer and Actions class.
Item triggers delete_task on button click.
@Item = React.createClass
render: ->
<label>{@props.item.note}</label>
<button
className="destroy"
onClick={@_onClick}
></button>
_onClick: (e) ->
Dispatcher.trigger 'delete_task', id: @props.item.id
Essential part of ASC:
@Todos = React.createClass
mixins: [ActionsHandler]
url: 'api/todos'
actions:
# handle delete_task action here:
delete_task: (params) ->
@todos.splice _.findIndex(@todos, id: params.id), 1
getInitialState: ->
todos: []
componentDidMount: ->
@listenForEvents()
$.get @url, (result) => @setState(result)
render: ->
<MainSection todos={@state.todos} /> # Item component is somewhere below MainSection
Handle action on the backend:
class TodosAction < ApplicationAction
def delete_task
Task.find_by(id: params[:id]).delete
end
end