index.js
- create store which is used to save state values
- bind reducers to store
reducers.js
- The reducer is a function that takes two parameters (state and action) to calculate and return an updated state
- combineReducers, connect the state features and their reducers
- action is automatically passed to all reducers
- reducer uses action type to decide how to update the state
actions.js
- JavaScript objects that use type property to inform about the data that should be sent to the store
App.js
- The App component is the root component of the app. Only the root component should be aware of a redux
- connect store with App with connect() function
- two parameters in connect(), one for get specific props from state, one for action which can triger the update of specific state values
Components shouldn't be aware of redux
//index.js
import React from 'react'
import { render } from 'react-dom'
import { createStore, applyMiddleware } from 'redux'
import {composeWithDevTools } from 'redux-devtools-extension';
import { Provider } from 'react-redux'
import App from './App.js'
import todoApp from './reducers/reducers'
let store = createStore(todoApp, {}, composeWithDevTools(applyMiddleware()));
let rootElement = document.getElementById('root')
render(
<Provider store = {store}>
<App />
</Provider>,
rootElement
)
//reducers.js
import { combineReducers } from 'redux'
import { ADD_TODO } from '../actions/actions'
function todo(state, action) {
switch (action.type) {
case ADD_TODO:
return {
id: action.id,
text: action.text,
}
default:
return state
}
}
function setAuthor(state = 'Lin', action) {
console.log("SetAuthor ...", state);
switch (action.type){
case ADD_TODO:
return 'Yanhua';
default:
return state
}
}
function todos(state = [], action) {
console.log('State in Reducer: ', typeof(state), state, action.type);
switch (action.type) {
case ADD_TODO:
return [
...state,
todo(undefined, action)
]
default:
return state
}
}
const todoApp = combineReducers({
stateTodos: todos, //let todos update stateTodos
author: setAuthor //let setAuthor update author
})
export default todoApp
//actions.js
export const ADD_TODO = 'ADD_TODO'
let nextTodoId = 0;
export function addTodo(text) {
console.log(nextTodoId);
return {
type: ADD_TODO,
id: nextTodoId++,
text: text
};
}
//App.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addTodo } from './actions/actions'
import AddTodo from './components/AddTodo.js'
import TodoList from './components/TodoList.js'
class App extends Component {
render() {
const { dispatch, visibleTodos, author } = this.props
console.log(dispatch, visibleTodos, author)
return (
<div>
<AddTodo onAddClick = {text =>dispatch(addTodo(text))} />
<TodoList todos = {visibleTodos}/>
</div>
)
}
}
function select(state) {
return {
visibleTodos: state.stateTodos,
author: state.author
}
}
export default connect(select)(App);
//AddTodo.js
import React, { Component, PropTypes } from 'react'
export default class AddTodo extends Component {
render() {
return (
<div>
<input type = 'text' ref = 'input' />
<button onClick = {(e) => this.handleClick(e)}>
Add
</button>
</div>
)
}
handleClick(e) {
const node = this.refs.input
const text = node.value.trim()
this.props.onAddClick(text)
node.value = '';
node.focus();
}
}
//TodoList.js
import React, { Component, PropTypes } from 'react'
import Todo from './Todo.js'
export default class TodoList extends Component {
render() {
return (
<ul>
{this.props.todos.map(todo =>
<Todo
key = {todo.id}
{...todo}
/>
)}
</ul>
)
}
}
//Todo.js
import React, { Component, PropTypes } from 'react'
export default class Todo extends Component {
render() {
return (
<li>
{this.props.text}
</li>
)
}
}