React - 如何重用/共享列表而不是全局

时间:2016-06-16 17:28:23

标签: javascript reactjs

作为开发人员,我希望能够在我的应用中的多个点重用数据源作为内容,例如待办事项列表。

我还想让我的组件决定他们想要使用哪种数据源。

每当修改列表时,组件都应更新

可以同时拥有具有不同数据源的多个组件(因此没有像大多数示例那样的全局存储)

  

todo列表的示例场景可能不是最好的,但是   简化问题的目的我决定使用这个

数据来源可能是例如:

  • AjaxTodoProvider,从某个地方的API加载ToDos
  • FooBarTodoProvider,它使用一些有趣的随机算法来创建一些
  • ...

组件可以是例如:

  • TodoListComponent,只显示所有ToDos
  • CarouselComponent,一次只显示一个ToDo。
  • ...

到目前为止我的尝试:(简单,不运行:D)

(不是工作的例子,只是在这里写下那些自由的手)

使用vanilla类作为数据提供者

class TodoProvider {
  // ...
  constructor() {
    this.list = ['Drink milk', 'Resolve this problem'];
  }
  getResults() {
    return list;
  }
}

class ToDoComponent extends React.Component {
  render() {
    return this.props.todos.map((todo) => <p key={todo}>{todo}</p>)
  }
}

class App extends React.Component {
  componentDidMount() {
    var todos = new ToDoComponent()
    this.setState({
      todos: todos.getResults()
    })
  }

  render() {
    return (
      <ToDoComponent todos={this.state.todos} />
    )
  }
}

这个问题:

  • 每当ToDo列表更改时,都不会自动更新

使用提供程序组件(上下文)

class ToDoProvider extends Component {
  constructor() {
    this.todos = ['Watch a great movie']
  }

  getChildContext() {
    return { todos: this.todos; }
  }

  render() { ... }
}


class App extends React.Component {
  render() {
    return (
      <ToDoProvider>
        <ToDoComponent todos={this.context.todos} />
      </ToDoProvider>
    )
  }
}

这个问题:

  • 上下文似乎并不是分享数据的最佳方式,因为它对整个子树来说是全局的?

使用提供程序组件(props)

class ToDoProvider extends Component {
  constructor() {
    this.state = {
      todos: ['Eat some sushi']
    }
  }

  render() {
    return React.cloneElement(this.props.children, {
      todos: this.state.todos
    })
  }
}


class App extends React.Component {
  render() {
    return (
      <ToDoProvider>
        <ToDoComponent todos={this.props.todos} />
      </ToDoProvider>
    )
  }
}

这个问题:

  • 也不是很好看?

所以我想知道解决这个问题最优雅的方法是什么?

1 个答案:

答案 0 :(得分:0)

您接近上下文示例:

class ToDoProvider extends Component {
  constructor() {
    this.state = {
      todos: ['Watch a great movie']
    };
  }

  getChildContext() {
    return { todos: this.state.todos };
  }

  render() {
    return this.props.children;
  }
}

class ToDoComponent extends Component {
  render() {
    return this.context.todos.map((todo) => <p key={todo}>{todo}</p>);
  }
}
ToDoComponent.contextTypes = { todos: React.PropTypes.any };

class App extends React.Component {
  render() {
    return (
      <ToDoProvider>
        <ToDoComponent />
      </ToDoProvider>
    )
  }
}

如果您希望在应用的多个级别和位置提供应用程序状态,则应该查看Redux(或至少是Flux库)。它可以帮助您将组件连接到不同的状态,而不需要手动编码。