Containers

Containers are our Presenter Model (see introduction to this chapter).

They hold our business logic and compose components to display the view.

In our application the view is simple.

--------------------------
| TodoForm               |
--------------------------
| TodoList               |
| - TodoItem             |
| - TodoItem             |
| - TodoItem             |
| ...                    |
|                        |
|                        |
|                        |
|                        |
--------------------------

TodoApp.jsx

import React, { Component, PropTypes } from 'react';
import { View } from 'react-native';
import TodoForm from '../components/TodoForm';
import TodoList from '../components/TodoList';
import TodoItem from '../components/TodoItem';
import { todoStore } from '../stores';
import styles from '../styles';

export default class TodoApp extends Component {
  constructor(props) {
    super(props);
    this.state = todoStore.getState();
  }

  // Business logic methods

  _onChange = (value) => {
    this.setState(value);
  }

  addTodo(text){
    todoStore.add(text);
  }

  onTodoClick(id) {
    todoStore.complete(parseInt(id));
  }

  onRemoveClick(id) {
    todoStore.remove(parseInt(id));
  }

  // React method

  componentDidMount() {
    todoStore.load();
    todoStore.changed.add(this._onChange);
  }

  componentWillUnmount() {
    todoStore.changed.remove(this._onChange);
  }

  render() {
    return (
      <View style={styles.container}>
        <TodoForm 
          style={styles.form}
          onAddTodo={this.addTodo}  />
        <TodoList
          todoRenderer={TodoItem}
          todoStyle={styles.todoItem}
          todoCompletedStyle={styles.todoItemCompleted}
          todos={this.state.todos}
          onTodoClick={this.onTodoClick}
          onRemoveClick={this.onRemoveClick} />
      </View>
    );
  }
}

Let's decompose this container.

  1. Import view components and compose the view
    The container compose a view with View Components we created before (TodoItem, TodoList, and TodoForm).
    This action is performed in the render() method of a React component.

    <View style={styles.container}>
       <TodoForm style={styles.form} />
       <TodoList 
           todoRenderer={TodoItem}
           todoStyle={styles.todoItem}
           todoCompletedStyle={styles.todoItemCompleted} />
    </View>
    
  2. Add data to the presenter model
    Data in our application leave in a Store. In order to import data in our presenter model we just import the store in the container.

    import todoStore from '../stores/todoStore';
    

    In React container can stock their data in the state of the React Component. Then those data are passed to the view using props.

  3. Link store state with container state
    This step occur in the constructor of the container. We give the store state as initial state of the container.

    this.state = todoStore.getState();
    
  4. Wired state and View Component props
    It's time now to link store data that is on the state with our view components to display them. We see in step 1 that view composition is done in the render() function. Data are passed to the view using props.

    <View style={styles.container}>
       <TodoForm style={styles.form} />
       <TodoList
         todoRenderer={TodoItem}
         todoStyle={styles.todoItem}
         todoCompletedStyle={styles.todoItemCompleted} 
         todos={this.state.todos}/>
    </View>
    

    we add the list of todos contains in our container state in the TodoList using todos props.

  5. Listen for data changes
    React component livecycle provide functions to know when respecticely a component is mount and unmout. We use this to listen for store changed signal and update the container state.

    _onChange(value) {
       this.setState(value);
    }
    componentDidMount() {
       todoStore.load();
       todoStore.changed.add(this._onChange);
    }
    componentWillUnmount() {
       todoStore.changed.remove(this._onChange);
    }
    
  6. Handling user interaction
    User will interact with view components in order to add, remove, update or change todos in the list. This interaction occur on View Component but the business logic will be handle by the Container. Data are managed by the Store. The Presenter Model/Container will only dispatch signal to prevent the store to update its state.

    • Write business functions that dispatch store signals
    addTodo(text){
     todoStore.add(text);
    }
    
    onTodoClick(id) {
     todoStore.complete(parseInt(id));
    }
    
    onRemoveClick(id) {
     todoStore.remove(parseInt(id));
    }
    
    • Link to view components
    <View style={styles.container}>
       <TodoForm 
         style={styles.form} 
         onAddTodo={this.addTodo}/>
       <TodoList
         todoRenderer={TodoItem}
         todoStyle={styles.todoItem}
         todoCompletedStyle={styles.todoItemCompleted} 
         todos={this.state.todos}
         onTodoClick={this.onTodoClick}
         onRemoveClick={this.onRemoveClick}
         />
    </View>
    

Components are now display by our Container which get its data from a store. Let's add Store Commands

results matching ""

    No results matching ""