README.md 2.33 KB
Newer Older
Nathan Faucett's avatar
Nathan Faucett committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# js-state-react

connect react components with state stores

## State Stores

```javascript
import State from "@nathanfaucett/state";

const state = new State();

let ID = 0;

const todos = state.createStore("todos", {
    list: []
});

todos.create = text => {
    const id = ID++;

    todos.updateState(state => {
        const list = state.list.slice();

        list.push({
            id: id,
            text: text
        });

        return {
            list: list
        };
    });
};

todos.remove = id => {
    todos.updateState(state => {
        const index = list.findIndex(todo => todo.id === id);

        let list = state.list;

        if (index !== -1) {
            list = list.slice();
            list.slice(index, 1);
        }

        return {
            list: list
        };
    });
};
```

## Components

```javascript
import React from "react";
import connect from "@nathanfaucett/state-react";
import state from "./state";
import todos from "./stores/todos";

// create store for form input
let todoListForm = state.createStore("todoListForm", { text: "" });

class TodoList extends React.Component {
    constructor(props) {
        super(props);

        this.onSubmit = e => {
            e.preventDefault();
            todos.create(this.props.todoListForm.text);
            todoListForm.setState({ text: "" });
        };

        this.onChange = e => {
            todoListForm.setState({ text: e.target.value });
        };
    }
    render() {
        return (
            <div class="TodoList">
                <form onSubmit={this.onSubmit}>
                    <input
                        value={this.props.todoListForm.text}
                        onChange={this.onChange}
                    />
                </form>
                {this.props.todos.list.map(todo => (
                    <p key={todo.id}>{todo.text}</p>
                ))}
            </div>
        );
    }
}

// update TodoList when todos or todoListForm emit an update
// on update adds todos state and todoListForm state to props
Nathan Faucett's avatar
Nathan Faucett committed
97
98
export default connect([todos, todoListForm], {
    mapping: (nextState, nextProps, props) => {
Nathan Faucett's avatar
Nathan Faucett committed
99
100
        // called on render should extract values from nextState to pass to component props
    },
Nathan Faucett's avatar
Nathan Faucett committed
101
    shouldUpdate: (prevState, nextState) => {
Nathan Faucett's avatar
Nathan Faucett committed
102
103
        // called on update, if returns false cancels update
    }
Nathan Faucett's avatar
Nathan Faucett committed
104
})(TodoList);
Nathan Faucett's avatar
Nathan Faucett committed
105
```