React - 从子组件

时间:2018-02-09 16:48:10

标签: reactjs

为noob问题道歉,但我对React来说是个新手。我在这里看到了一些类似的问题,但我相信我的要求略有不同。

我正在创建一个Accordion组件,它是子AccordionItem组件的父组件。我给每个AccordionItem一个自己的状态来跟踪项目是处于打开还是关闭状态。这很好用,我现在有一个工作的手风琴,当你点击项目的标题时,每个项目都可以打开或关闭。

但是我现在想要添加功能,如果AccordionItem已经处于打开状态,它将在选择另一个AccordionItem时关闭。我相信我需要一个状态数组或对象在我的Accordion.js中,它跟踪当前选择的AccordionItems,然后每次点击都会更新。

我正在努力研究如何将父方法传递给子组件。

我的App.js目前如下所示:

class App extends Component {
  render() {
    return (
      <Accordion>
        <AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
          <p>here is some text 1</p>
        </AccordionItem>
        <AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
          <p>here is some text 2</p>
        </AccordionItem>
        <AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
          <p>here is some text 3</p>
        </AccordionItem>
      </Accordion>
    );
  }

}

我在网上看到的所有例子都显示父母有一个道具,它将所选父方法的引用传递给子组件。但是因为我的AccordionItems在App.js中定义而不是Accordion.js this.updateSelectedItems在此文件中不存在。

我不想将AccordionItems移动到手风琴中,因为每个手风琴都会有相同的数据。

思想?

4 个答案:

答案 0 :(得分:1)

这是我扔在一起的东西。在这里工作JSFiddle:https://jsfiddle.net/gkysmsqz/6/

Accordion应保持应显示手风琴部分的活动指数。你可以克隆每个孩子并在渲染之前为他们添加一些额外的道具(在下面的例子中为activetoggleSection):

class App extends React.Component {
  render() {
    return (
      <Accordion>
        <AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
          <p>here is some text 1</p>
        </AccordionItem>
        <AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
          <p>here is some text 2</p>
        </AccordionItem>
        <AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
          <p>here is some text 3</p>
        </AccordionItem>
      </Accordion>
    );
  }
}

class Accordion extends React.Component {
    state = {
    activeIndex: 0
  };

  toggleSection = index => {
    this.setState({
        activeIndex: index
    });
  };

    render() {
    const rows = this.props.children.map( (child, i) => {
        return React.cloneElement(child, { active: i === this.state.activeIndex, toggleSection: this.toggleSection.bind(this, i) });
    });
    return (
        <div>
          {rows}
        </div>
    );
  }
}

const AccordionItem = props => (
  <div>
    <span onClick={props.toggleSection}>{props.title}</span>
    <div className={props.active ? 'active accordion-item' : 'accordion-item'}>
      {props.children}
    </div>
  </div>
);

答案 1 :(得分:0)

我认为您可能会发现这篇文章很有用https://reactjs.org/docs/composition-vs-inheritance.html

在您的情况下,您可以在Accordion组件的render方法中执行以下操作:

render() {
  return (
    <div>
    {
      this.props.children.map(
        child => {
          child.passedMethod = this.updateSelectedItems;
          return child;
        }
      )
    }
    </div>
  );
}

答案 2 :(得分:-1)

如果Accordion正在跟踪AccordionItem组件,那么你应该让Accordion处理AccordionItems的渲染。

App.js

class App extends Component {
  render() {
    return
      <Accordion />;
  }

Accordion.js

updateItems = () => ...

render() {
  return (
    <div>
            <AccordionItem title="Question One Title" itemid="question1" openOnLoad onChange={this.updateSelectedItems}>
              <p>here is some text 1</p>
            </AccordionItem>
            <AccordionItem title="Question Two Title" itemid="question2" onChange={this.updateSelectedItems}>
              <p>here is some text 2</p>
            </AccordionItem>
            <AccordionItem title="Question Three Title" itemid="question3" onChange={this.updateSelectedItems}>
              <p>here is some text 3</p>
            </AccordionItem>
    </div>
  );
}

答案 3 :(得分:-1)

按照Reactjs的基础知识,在Parent(Accordion)中保持你的状态,并将该状态传递给所有的孩子(AccordionItem)。此外,您需要传递一个事件处理程序(将更新父状态),当选择任何子项(AccordionItem)时将调用它。