在表示组件中嵌套容器组件



我试图重构我的应用程序,以分离表示和容器组件。我的容器组件只是包装在来自react-redux的connect()调用中的表示组件,它将状态和操作创建者映射到表示组件的props。

todo-list.container.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {fetchTodos} from '../actions/todo.actions';
import TodoList from '../components/todo-list.component';
export default connect(({todo}) => ({state: {todo}}), {fetchTodos})(TodoList);

todo-list.component.jsx

import React, {Component} from 'react';
import TodoContainer from '../containers/todo.container';
export default class TodoList extends Component {
    componentDidMount () {
        this.props.fetchTodos();
    }
    render () {
        const todoState = this.props.state.todo;
        return (
            <ul className="list-unstyled todo-list">
                {todoState.order.map(id => {
                    const todo = todoState.todos[id];
                    return <li key={todo.id}><TodoContainer todo={todo} /></li>;
                })}
            </ul>
        );
    }
};

todo.container.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {createTodo, updateTodo, deleteTodo} from '../actions/todo.actions';
import Todo from '../components/todo.component';
export default connect(null, {createTodo, updateTodo, deleteTodo})(Todo);

todo.component.jsx

import React, {Component} from 'react';
import '../styles/todo.component.css';
export default class Todo extends Component {
    render () {
        return (
            <div className="todo">
                {todo.description}
            </div>
        );
    }
};

我想弄清楚的是:我知道我应该<TodoContainer />元素嵌入TodoList内部,因为TodoList是一个表示组件,它应该只在其中嵌套其他表示组件。但如果我将其替换为<Todo />表示组件,那么我就必须映射Todo组件所需的TodoListContainer中的每个状态道具和动作创建器道具,并将它们作为道具手动传递给整个链。这当然是我想要避免的,特别是当我开始嵌套更多关卡或开始依赖来自Redux的更多道具时。

我接近这个正确吗?一般来说,我似乎不应该尝试将容器组件嵌入到表示组件中,因为如果我可以将表示组件与Redux解耦,它们就会变得更易于重用。同时,我不知道如何将一个需要访问Redux状态/调度的组件嵌入到任何其他具有标记的组件中。

具体回答您的问题:可以嵌套表示组件和容器组件。毕竟,它们都只是组成部分。但是,为了便于测试,我更喜欢嵌套表示组件,而不是容器组件。这一切都归结为组件的清晰结构。我发现从单个文件开始,然后慢慢地组成组件效果很好。

了解嵌套子元素和使用this.props.children在表示组件中包装子元素。

示例(为了简洁,删除了一些代码)

List(表示组件)

import React, { Component, PropTypes } from 'react';
export default class List extends Component {
  static propTypes = {
    children: PropTypes.node
  }
  render () {
    return (
      <div className="generic-list-markup">
        {this.props.children} <----- wrapping all children
      </div>
    );
  }
}

Todo(表示组件)

import React, { Component, PropTypes } from 'react';
export default class Todo extends Component {
  static propTypes = {
    description: PropTypes.string.isRequired
  }
  render () {
    return (
      <div className="generic-list-markup">
        {this.props.description}
      </div>
    );
  }
}

TodoList (container component)

import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { createTodo, updateTodo, deleteTodo } from 'actions';
import List from 'components/List';
import Todo from 'components/Todo';
export class TodoList extends Component {
  static propTypes = {
    todos: PropTypes.array.isRequired,
    create: PropTypes.func.isRequired
  }
  render () {
    return (
      <div>
        <List> <---------- using our presentational component
          {this.props.todos.map((todo, key) =>
            <Todo key={key} description={todo.description} />)}
        </List>
        <a href="#" onClick={this.props.create}>Add Todo</a>
      </div>
    );
  }
}
const stateToProps = state => ({
  todos: state.todos
});
const dispatchToProps = dispatch = ({
  create: () => dispatch(createTodo())
});
export default connect(stateToProps, dispatchToProps)(TodoList);

DashboardView(表示组件)

import React, { Component } from 'react';
import TodoList from 'containers/TodoList';
export default class DashboardView extends Component {
  render () {
    return (
      <div>
        <TodoList />
      </div>
    );
  }
};

相关内容

  • 没有找到相关文章

最新更新