ReactJS:Dynamic previous&下一个按钮

时间:2017-07-11 21:53:34

标签: javascript reactjs

我是ReactJS的新手,并试图了解如何使用最佳实践来完成基本概念。下面的代码将呈现项目列表,当单击某个项目时,切换有状态 组件并将数据从 传递到 状态对象在重新渲染之前被消费。

我需要帮助的是从下面的数组示例中检索兄弟姐妹数据的方法。为上一个/下一个项目提取数据后, 组件可以访问数据。可以使用键值访问这些兄弟姐妹吗?如果是这样,我将如何使用密钥?

数据

window.Seed = (function() {
  const projects = [
    {id:1, title:'Project 1', description:'Project 1 Description'},
    {id:2, title:'Project 2', description:'Project 2 Description'},
    {id:3, title:'Project 3', description:'Project 3 Description'}
  ]
};

REACT CODE:

class ProjectList extends React.Component {

  state = {
    projects: [],
    isOpen: false,
    modalTitle: '',
    modalDescription: '',
    modalId: ''
  }

  componentDidMount() {
    this.setState({ projects: Seed.projects });
  }

  handleModalOpen = (id, title, description) => {
    this.setState({
      isOpen: true,
      modalId: id,
      modalTitle: title,
      modalDescription: description
    });
  };

  handleModalClose = () => {
    this.setState({ isOpen: false });
  };

  render() {
    const projects = this.state.projects;

    // GOAL #1: Pass previous/next project data as props
    // =================================================
    // Pass projects.map data from previous & next siblings
    // to the current component or explore a new method to 
    // retrieve data from state? I can already tell that this
    // probably is not the most dynamic approach to handle
    // previous/next data.

    const projectComponents = projects.map((project) => (
      <Project
        key={'project-' + project.id}
        id={project.id}
        title={project.title}
        url={project.url}
        description={project.description}
        background={project.background}
        onModalOpen={this.handleModalOpen}
        prevTitle={???}
        nextTitle={???}
        prevDescription={???}
        nextDescription={???}
      />
    ));

    if (this.state.isOpen) {
      return (
        <Modal
          id={this.state.modalId}
          title={this.state.modalTitle}
          description={this.state.modalDescription}
          onModalClose={this.handleModalClose}
        />
      );
    } else {
      return (
        <div className="projects-container">
          <div id="projects" className="wrapper">
            {projectComponents}
          </div>
        </div>
      );
    }
  }
}

class Project extends React.Component {
  render() {
    return (
      <aside className='item'>
        <a onClick={this.props.onModalOpen.bind(
          this, this.props.id, this.props.title, this.props.description
          // I think that I need to bind previous/next data here on click.
          // this.props.prevTitle, this.props.nextTitle
          // this.props.prevDescription, this.props.nextDescription
        )}>
          <img src={this.props.background} />
        </a>
      </aside>
    );
  }
}

class Modal extends React.Component {
  render() {
    return (
      <div className="modal">

        // GOAL #2: Get sibling data from mapped array
        // =================================================
        // I would like to be able to pass previous and next
        // project data as props to populate these headings.

        <h2>Current Project: {this.props.title}</h2>
        <h2>Previous Project: {this.props.prevTitle} </h2>
        <h2>Next Project: {this.props.nextTitle} </h2>

        // GOAL #3: Replace content with data stored in state
        // =================================================
        // I would like to be able to 'onClick' these buttons 
        // to replace the content of the <Modal />. Essentially,
        // this should behave like a lightbox or carousel.

        // Initial Project Description
        <p>{this.props.description}</p>

        // this.props.description = this.props.prevDescription
        <button onClick={???}>Previous Project</button>

        // this.props.description = this.props.nextDescription
        <button onClick={???}>Next Project</button>
        <button onClick={this.props.onModalClose}>Close Modal</button>

      </div>
    );
  }
}

DEMO

感谢阅读!

UPDATED SOLUTION

1 个答案:

答案 0 :(得分:0)

作为一般原则,数据应该通过React组件从父到子流动,而不是从兄弟到兄弟。从理论上讲,有可能在兄弟姐妹之间传递数据,但这会使数量级更复杂。自上而下数据流的优点在于,无论父项中的数据发生更改,子项都会(可能会排除纯渲染等优化)重新渲染。因此,您只需更改父级中的数据,子级将根据需要自动更新。以下是以这种方式实现目标的建议。这并不完美,但我希望它说明了这一点:

目标#1:Array.prototype.map使用以下参数的函数:function(currentValue, index, array) {...}。对于每个项目,上一个项目为array[index - 1],下一个项目为array[index + 1]。您所要做的就是在map函数中以这种方式引用上一个和下一个项目,以获取它们的标题,描述等。

目标#2:使用this.state.isOpen而不是this.state.activeProject。单击项目时,将this.state.activeProject设置为该项目的索引。然后,如果!!this.state.activeProject(如果this.state.activeProject是真实的),您可以推断模态是打开的。使用activeProject id / index将所需数据从该项目传递到ProjectList组件呈现方法中的Modal组件。

目标#3:将this.state.activeProject更新为上一个或下一个项目的索引/ ID。这将导致使用新道具重新渲染ProjectList。为此,您需要传递onNextClickonPrevClick道具。您可以分别将this.state.activeProject + 1this.state.activeProject - 1部分应用于onNextClickonPrevClick