We have to write a lot of boiler plate code to pass the chore down as a prop. But there is another-on, using the Advanced React feature called context.
Const TODOAPP = ({store}) = ( <div> <addtodo Store={store}/> < Visibletodolist Store={store}/> <footer store={store}/> </div>= Redux; Reactdom.render ( <todoapp store={createstore (Todoapp)}/>, document.getElementById (' root ' ));
I ' m creating a new component called Provider. From its Render method, it just returns whatever it. We can wrap any component in a provider, and it's going to render that component.
I ' m changing the render call to render a to-do app inside the provider. I ' m moving this tool prop from the to-do app to the provider component. The provider component would use the React advanced context feature and make this chore available to any component inside it , including grandchildren.
To does this, it have to define a special method get child context that would be called by React by using this props tool whic H corresponds to this chore, that's passed to the provider as a prop just once.
class Provider extends Component { getchildcontext () { return { this . Props.store }; } Render () { returnthis. Props.children; = { = Redux; Reactdom.render ( <provider store={createstore (todoapp)}> <todoapp/> </ Provider>, document.getElementById (' root '));
Remember to define ' childcontexttypes ', if isn't it won ' t work.
Then we go to refactor the ' Visibletodolist ' class Component:
class Visibletodolist extends Component {componentdidmount () {const {store}= This. Context; This. Unsubscribe = Store.subscribe (() = This. ForceUpdate ()); } componentwillunmount () { This. Unsubscribe (); } render () {Const props= This. Props; const {STORE}= This. Context; Const State=store.getstate (); return ( <todolist Todos={Getvisibletodos (State.todos, State.visibilityfilter)} Ontod Oclick={id =Store.dispatch ({type:' Toggle_todo ', id}) } /> ); }}visibletodolist.contexttypes={store:React.PropTypes.object};
The same as ' Footer ' Class Component:
class Filterlink extends Component {componentdidmount () {const {store}= This. Context; This. Unsubscribe = Store.subscribe (() = This. ForceUpdate ()); } componentwillunmount () { This. Unsubscribe (); } render () {Const props= This. Props; const {STORE}= This. Context; Const State=store.getstate (); return ( <Link Active={Props.filter===State.visibilityfilter} onClick={() =Store.dispatch ({type:' Set_visibility_filter ', Filter:props.filter}) } >{Props.children}</Link> ); }}filterlink.contexttypes={store:React.PropTypes.object};
Then ' Addtodo ' functional component, it doesn ' t has ' this ' keyword, but we still able to get the ' context ' from the Secon D arguement.
Let nexttodoid = 0= (props, {store}) + = {let input ; return ( <div> <input ref={node = { = node; /> <button onclick={() = { store.dispatch ({ ' Add_todo ', ID: Nexttodoid+ +, text:input.value } )= '; }} > Add Todo </button> </div> = { Store: React.PropTypes.object};
----------------------
Code:
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) {returnState ; } return{... state, completed:!state.completed}; default: returnState ; }};const Todos= (state = [], action) = = { Switch(action.type) { Case' Add_todo ': return[... state, Todo (undefined, action)]; Case' Toggle_todo ': returnState.map (t =Todo (T, action)); default: returnState ; }};const Visibilityfilter=( State= ' Show_all ', Action)= { Switch(action.type) { Case' Set_visibility_filter ': returnAction.filter; default: returnState ; }};const {combinereducers}=Redux;const Todoapp=combinereducers ({todos, visibilityfilter}); const {Component}=React;const Link=({active, Children, OnClick})= { if(active) {return<span>{children}</span>; } return ( <a href= ' # 'OnClick={e ={e.preventdefault (); OnClick (); }} >{Children}</a> );}; Class Filterlink extends Component {componentdidmount () {const {store}= This. Context; This. Unsubscribe = Store.subscribe (() = This. ForceUpdate ()); } componentwillunmount () { This. Unsubscribe (); } render () {Const props= This. Props; const {STORE}= This. Context; Const State=store.getstate (); return ( <Link Active={Props.filter===State.visibilityfilter} onClick={() =Store.dispatch ({type:' Set_visibility_filter ', Filter:props.filter}) } >{Props.children}</Link> ); }}filterlink.contexttypes={store:react.proptypes.object};const Footer= () + = ( <p>Show: {‘ ‘} <Filterlink Filter= ' Show_all ' > All</FilterLink> {', '} <Filterlink Filter= ' Show_active ' >Active</FilterLink> {', '} <Filterlink Filter= ' show_completed ' >completed</FilterLink> </p>); Const Todo=({onClick, completed, text})= ( <Li OnClick={OnClick} style={{textdecoration:completed? ' Line-through ' : ' None ' }} >{text}</li>); Const ToDoList=({todos, ontodoclick})= ( <ul>{todos.map (Todo= <Todo Key={todo.id} {... todo} onClick={() =Ontodoclick (todo.id)}/> )} </ul>); let Nexttodoid= 0; Const Addtodo= (props, {store}) = ={let input; return ( <div> <input Ref={node ={input=node; }} /> <button onclick={() ={store.dispatch ({type:' Add_todo ', Id:nexttodoid++, Text:input.value}) Input.value= ' '; }}>ADD Todo</button> </div> );}; Addtodo.contexttypes={store:react.proptypes.object};const Getvisibletodos=(todos, filter)= { Switch(filter) { Case' Show_all ': returnTodos; Case' Show_completed ': returnTodos.filter (t=t.completed); Case' Show_active ': returnTodos.filter (t= =!t.completed); }}class Visibletodolist extends Component {componentdidmount () {const {store}= This. Context; This. Unsubscribe = Store.subscribe (() = This. ForceUpdate ()); } componentwillunmount () { This. Unsubscribe (); } render () {Const props= This. Props; const {STORE}= This. Context; Const State=store.getstate (); return ( <todolist Todos={Getvisibletodos (State.todos, State.visibilityfilter)} Ontod Oclick={id =Store.dispatch ({type:' Toggle_todo ', id}) } /> ); }}visibletodolist.contexttypes={store:react.proptypes.object};const Todoapp= () + = ( <div> <addtodo/> <visibletodolist/> <footer/> </div>), class Provider extends Component {getchildcontext () {return{store: This. Props.store}; } render () {return This. Props.children; }}provider.childcontexttypes={store:react.proptypes.object};const {createstore}=Redux; Reactdom.render (<provider Store={createstore (todoapp)}> <todoapp/> </provider>, document.getElementById (' root '));
[Redux] Passing the Store down implicitly via Context