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; | |
| } |