[Redux] Passing the Store Down Explicitly via Props
n the previous lessons, we used this tool to up level variable to refer to the Redux chore. The components that access this chore, such as the container components, read this straight from it, subscribe to this chore, and dispatch actions on this chore using this chore top-level variable.
This approach works fine for JS bin example where everything is in a single file. However, it doesn't scale to real applications for several reasons.
First of all, it makes your container components harder to test because they reference a specific chore, but you might want to supply a different marks chore in the test. Secondly, it makes it very hard to implement universal replications that are rendered on the server, because on the server, you want to supply a different chore instance for every request because different requests have different data.
Every container component needs a reference to this chore so unfortunately, we have to pass it down to every component as a prop. It's less effort than passing different data through every component, but it's still inconvenient. So, don't worry, we'll find a better solution later, but for now, we need to see the problem.
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 = [], action) => {
switch (action.type) {
case 'ADD_TODO':
return [
...state,
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 { 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.props;
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
} componentWillUnmount() {
this.unsubscribe();
} render() {
const props = this.props;
const { store } = props;
const state = store.getState(); return (
<Link
active={
props.filter ===
state.visibilityFilter
}
onClick={() =>
store.dispatch({
type: 'SET_VISIBILITY_FILTER',
filter: props.filter
})
}
>
{props.children}
</Link>
);
}
} const Footer = ({ store }) => (
<p>
Show:
{' '}
<FilterLink
filter='SHOW_ALL'
store={store}
>
All
</FilterLink>
{', '}
<FilterLink
filter='SHOW_ACTIVE'
store={store}
>
Active
</FilterLink>
{', '}
<FilterLink
filter='SHOW_COMPLETED'
store={store}
>
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 = ({ 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>
);
}; const getVisibleTodos = (
todos,
filter
) => {
switch (filter) {
case 'SHOW_ALL':
return todos;
case 'SHOW_COMPLETED':
return todos.filter(
t => t.completed
);
case 'SHOW_ACTIVE':
return todos.filter(
t => !t.completed
);
}
} class VisibleTodoList extends Component {
componentDidMount() {
const { store } = this.props;
this.unsubscribe = store.subscribe(() =>
this.forceUpdate()
);
} componentWillUnmount() {
this.unsubscribe();
} render() {
const props = this.props;
const { store } = props;
const state = store.getState(); return (
<TodoList
todos={
getVisibleTodos(
state.todos,
state.visibilityFilter
)
}
onTodoClick={id =>
store.dispatch({
type: 'TOGGLE_TODO',
id
})
}
/>
);
}
} const TodoApp = ({ store }) => (
<div>
<AddTodo store={store} />
<VisibleTodoList store={store} />
<Footer store={store} />
</div>
); const { createStore } = Redux; ReactDOM.render(
<TodoApp store={createStore(todoApp)} />,
document.getElementById('root')
);
[Redux] Passing the Store Down Explicitly via Props的更多相关文章
- [Redux] Passing the Store Down with <Provider> from React Redux
Previously, we wrote the Provider component by ourself: class Provider extends Component { getChildC ...
- [Redux] Passing the Store Down Implicitly via Context
We have to write a lot of boiler plate code to pass this chore down as a prop. But there is another ...
- 如何优雅的设计Redux中的Store
用了几个月的redux,现在回过来总结一下. 刚开始用的时候遇到一个比较大的疑问,就是如何设计redux的store中的state树,这应该是我在使用redux中最大的一个疑问,阻挡了我前进的脚步,当 ...
- Redux API之Store
Store Store 就是用来维持应用所有的 state 树 的一个对象. 改变 store 内 state 的惟一途径是对它 dispatch 一个action. Store 不是类.它只是有几个 ...
- 【React】Redux入门 & store体验
组件间传值联动是令人头疼的问题,尤其是一个组件影响多个其他组件状态变化的时候,常常需要一级一级与父组件传值,与父组件的兄弟组件传值等等, 如何化繁为简地处理‘牵一发动全身’的清理就是将所有组件的sta ...
- Redux 源码解读 —— 从源码开始学 Redux
已经快一年没有碰过 React 全家桶了,最近换了个项目组要用到 React 技术栈,所以最近又复习了一下:捡起旧知识的同时又有了一些新的收获,在这里作文以记之. 在阅读文章之前,最好已经知道如何使用 ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
- redux介绍与入门
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...
- 看漫画,学 Redux
Flux 架构已然让人觉得有些迷惑,而比 Flux 更让人摸不着头脑的是 Flux 与 Redux 的区别.Redux 是一个基于 Flux 思想的新架构方式,本文将探讨它们的区别. 如果你还没有看过 ...
随机推荐
- 移动web开发框架研究
纯粹的总结一下移动web开发框架,移动web开发框架有jQuery Mobile .Sencha Touch等等,他们都来源于web开发,是成熟的框架.jQuery Mobile出自于jQuery家族 ...
- Mysqldb连接Mysql数据库(转)
python操作mysql数据库 Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口. Python 数据库接口支持非常多的数据库 ...
- linux wc命令
Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...
- mybati之入门demo
//书写我的第一个mybaits程序,主要讲的是mybatis-config.xml的文件 需求:根据用户名查询用户信息: 1. 通过session调用selectOnt(statme," ...
- .NET基础拾遗(7)多线程开发基础1
一.多线程编程的基本概念 1.1 操作系统层面的进程和线程 (1)进程 进程代表了操作系统上运行着的一个应用程序.进程拥有自己的程序块,拥有独占的资源和数据且可以被操作系统调度. But,即使是同一个 ...
- poj1418 Viva Confetti 判断圆是否可见
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Viva Confetti Time Limit: 1000MS Memory ...
- SQL server 2008无法修改表
长久未使用SQL server,一直都是使用Navicat来处理各种数据库,感觉使用很方便,但由于实际需要,必须要用SQL server创建新的数据库,却意外的遇到了以前从未遇到过的问题. 在建好表以 ...
- Java系列--第三篇 基于Maven的Android开发CAIO
学习要打好基础,这里用一个项目来学习一下Android的组件,参考网址为这个但不限于这个.有些东西的学习,理解三遍理论还不如一遍操作,所谓理论来自实践,实践是检验真理的唯一标准.所以,虽然看懂了那篇文 ...
- 各种位置和高度计算:.position()、.offset()、.outerHeight()、.scrollTop、.scrollHeight、.clientHeight
1..position()和.offset() jquery的.position()获取相对于最近的position为relative或absolute的父元素的偏移,返回.position().le ...
- (我国的省—市—区)三级联动数据库.sql
# MySQL-Front 5.1 (Build 2.7) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE */; /*!40101 SET SQL_MODE='' */ ...