find a better way to solve the connect problem when the parent component and the child component connect different data using react-redux at the using of immutable.
A Pen by Junhui Feng on CodePen.
#root |
find a better way to solve the connect problem when the parent component and the child component connect different data using react-redux at the using of immutable.
A Pen by Junhui Feng on CodePen.
// action type | |
const ADD_TODO = 'ADD_TODO' | |
const TOGGLE_TODO = 'TOGGLE_TODO' | |
const SHOW_ALL = 'SHOW_ALL' | |
const SHOW_ACTIVE = 'SHOW_ACTIVE' | |
const SHOW_COMPLETED = 'SHOW_COMPLETED' | |
const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER' | |
const { createStore, combineReducers} = Redux | |
const { Component , addons } = React | |
// const { PureRenderMixin } = addons; | |
const {fromJS} = Immutable | |
const { Provider, connect } = ReactRedux | |
// reducers | |
const todo = (state, action) => { | |
switch (action.type) { | |
case ADD_TODO: | |
return { | |
id: action.id, | |
text: action.text, | |
completed: false | |
} | |
case TOGGLE_TODO: | |
if (state.id !== action.id) { | |
return state | |
} | |
return { | |
...state, | |
completed: !state.completed | |
} | |
default: | |
return state | |
} | |
} | |
const todos = (state = fromJS([]), action) => { | |
switch (action.type) { | |
case 'ADD_TODO': | |
return state.push(fromJS(todo(undefined, action))) | |
case TOGGLE_TODO: | |
return state.map(t => todo(t, action)) | |
default: | |
return state | |
} | |
} | |
const visibilityFilter = (state = SHOW_ALL, action) => { | |
switch (action.type) { | |
case SET_VISIBILITY_FILTER: | |
return action.filter | |
default: | |
return state | |
} | |
} | |
const todoApp = combineReducers({ | |
todos, | |
visibilityFilter | |
}) | |
const FilterLink = ({filter, children}) => { | |
return ( | |
<a className='link' href='#' | |
onClick={e => { | |
e.preventDefault() | |
store.dispatch({ | |
type: SET_VISIBILITY_FILTER, | |
filter | |
}) | |
}}> | |
{children} | |
</a> | |
) | |
} | |
let nextTodoId = 0 | |
const ItemDesc = React.createClass ({ | |
// mixins: [PureRenderMixin], | |
render() { | |
console.log('TodoitemDES this.props : ', this.props) | |
const {visibilityFilter} = this.props | |
return ( | |
<span className={`${visibilityFilter} itemdes`}> | |
{visibilityFilter} | |
</span> | |
) | |
} | |
}) | |
const TodoItemDESMapStateToProps = (state, props) => ({visibilityFilter: state.visibilityFilter}) | |
const ItemDESContainer = connect(TodoItemDESMapStateToProps)(ItemDesc) | |
const TodoItem = React.createClass ({ | |
// mixins: [PureRenderMixin], | |
render() { | |
console.log('Todoitem this.props : ', this.props) | |
let {todo} = this.props; | |
todo = todo.toJS(); | |
return ( | |
<li key={todo.id} | |
onClick={() => { | |
store.dispatch({ | |
type: TOGGLE_TODO, | |
id: todo.id | |
}) | |
}} | |
style={{ | |
textDecoration: | |
todo.completed ? | |
'line-through' : 'none' | |
}}> | |
{todo.text} | |
<ItemDESContainer name='shirly'/> | |
</li> | |
) | |
} | |
}) | |
const TodoItemMapStateToProps = (state, props) => ({...props}) | |
// const TodoItemMapStateToProps = (state, props) => ({...props, visibilityFilter: state.visibilityFilter}) | |
const TodoItemContainer = connect(TodoItemMapStateToProps)(TodoItem) | |
const TodoApp = React.createClass ({ | |
// mixins: [PureRenderMixin], | |
render() { | |
const {todos} = this.props | |
return ( | |
<div> | |
<input ref={node => { | |
this.input = node | |
}}/> | |
<button onClick={() => { | |
store.dispatch({ | |
type: ADD_TODO, | |
text: this.input.value, | |
id: nextTodoId++ | |
}) | |
this.input.value = '' | |
}}> | |
Add Todo | |
</button> | |
<ul> | |
{todos.map(todo => | |
<TodoItemContainer todo={todo}/> | |
)} | |
</ul> | |
<p> | |
Show: | |
<FilterLink filter='SHOW_ALL'>All</FilterLink> | |
<FilterLink filter='SHOW_ACTIVE'>Active</FilterLink> | |
<FilterLink filter='SHOW_COMPLETED'>Completed</FilterLink> | |
</p> | |
</div> | |
) | |
} | |
}) | |
const TodoMapStateToProps = (state) => ({todos: state.todos}) | |
const TodoContainer = connect(TodoMapStateToProps)(TodoApp) | |
const element = document.getElementById('root') | |
const store = createStore(todoApp) | |
const render = () => { | |
ReactDOM.render( | |
<Provider store={store}> | |
<TodoContainer/> | |
</Provider> | |
, | |
element | |
) | |
} | |
render() | |
console.log('state: ', store.getState()) |
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.4.4/babel.min.js"></script> | |
<script src="https://fb.me/react-with-addons-0.14.0.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.3.1/redux.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.7.5/immutable.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.1/react-redux.min.js"></script> |
.link { | |
margin-left: 10px; | |
margin-right: 10px; | |
} | |
.SHOW_COMPLETED { | |
color: red; | |
} | |
.SHOW_ACTIVE { | |
color: green; | |
} | |
.itemdes { | |
margin-left: 50px; | |
} |