Usage with React-Router
文章目录

Redux: Usage with React-Router

首先,我们需要从 React Router 中导入 <Router /><Route />。代码如下:

1
import { Router, Route, browserHistory } from 'react-router';

在 React 应用中,通常你会用 <Router /> 包裹 <Route />。 如此,当 URL 变化的时候,<Router /> 将会匹配到指定的路由,然后渲染路由绑定的组件。 <Route /> 用来显式地把路由映射到应用的组件结构上。 用 path 指定 URL,用 component 指定路由命中 URL 后需要渲染的那个组件。

1
2
3
4
5
const Root = () => (
  <Router>
    <Route path="/" component={App} />
  </Router>  
);

然后,我们从 React Redux 导入 <Provider />

1
import { Provider } from 'react-redux';

我们将用 <Provider /> 包裹 <Router />,以便于路由处理器可以访问 store(暂时未找到相关中文翻译,译者注)。

**
Provider 实际上仅仅做了一个核心操作,就是将 store 设置到 context 里面import { Provider } from ‘react-redux’;
,这样它里面包裹的所有 childElem 都可以访问 store
**

1
2
3
4
5
6
7
8
9
10
11
12


import { Router, Route, browserHistory } from 'react-router';


const Root = ({ store }) => (
  <Provider store={store}>
    <Router>
      <Route path="/(:filter)" component={App} />
    </Router>
  </Provider>
);

React Router 提供了 <Link /> 来实现导航功能。 下面将举例演示。现在,修改我们的容器组件 <FilterLink /> ,这样我们就可以使用 <FilterLink /> 来改变 URL。你可以通过 activeStyle 属性来指定激活状态的样式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import { Link } from 'react-router';

const FilterLink = ({ filter, children }) => (
  <Link
    to={filter === 'all' ? '' : filter}
    activeStyle={{
      textDecoration: 'none',
      color: 'black'
    }}
  >
    {children}
  </Link>
);

export default FilterLink;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react'
import FilterLink from '../containers/FilterLink'

const Footer = () => (
  <p>
    Show:
    {" "}
    <FilterLink filter="all">
      All
    </FilterLink>
    {", "}
    <FilterLink filter="active">
      Active
    </FilterLink>
    {", "}
    <FilterLink filter="completed">
      Completed
    </FilterLink>
  </p>
);

export default Footer

这时,如果你点击 <FilterLink />,你将看到你的 URL 在 '/complete''/active''/' 间切换。 甚至还支持浏览的回退功能,可以从历史记录中找到之前的 URL 并回退。

从 URL 中读取数据(将 component 和 URL 连接起来)

但是上面的修改还不够, URL 变化不会影响 component 细节, 因为到这一步为止我们还没有将 component 和 URL 连接起来

现在,即使 URL 改变,todo 列表也不会被过滤。 这是因为我们是在 <VisibleTodoList />mapStateToProps() 函数中过滤的。 这个目前仍然是和 state 绑定,而不是和 URL 绑定。mapStateToProps 的第二可选参数 ownProps,这个是一个传递给 <VisibleTodoList /> 所有属性的对象。

所以修改一下 mapStateToProps

1
2
3
4
5
6
7
// 注意这里多传了一个ownProps参数
const mapStateToProps = (state, ownProps) => {
  return {
    todos: getVisibleTodos(state.todos, ownProps.filter) 
    // 以前是 getVisibleTodos(state.todos, state.visibilityFilter)
  };
};

然后因为上文我们已经提供了 <Route path="/(:filter)" component={App} />,因此我们可以在 App 中获取 params 的属性。

params 是一个包含 url 中所有指定参数的对象。 _例如:如果我们访问 localhost:3000/completed,那么 params 将等价于 { filter: 'completed' }。 现在,我们可以在 <App /> 中读取 URL 参数了。

下一步就是在 App 里面添加一个 prop: filter 给上方的 ownProps.filter 使用。

1
2
3
4
5
6
7
8
9
10
11
const App = ({ params }) => {
  return (
    <div>
      <AddTodo />
      <VisibleTodoList
        filter={params.filter || 'all'}
      />
      <Footer />
    </div>
  );
};