Как вызвать обработчик события или метод в дочернем компоненте от родителя? - PullRequest
1 голос
/ 13 марта 2019

Я пытаюсь реализовать нечто похожее на кнопку с плавающим действием (FAB) в документации Material-UI:

https://material -ui.com / demos / buttons / # floating-кнопки действия

У них есть что-то вроде:

<SwipeableViews>
  <TabContainer dir={theme.direction}>Item One</TabContainer>
  <TabContainer dir={theme.direction}>Item Two</TabContainer>
  <TabContainer dir={theme.direction}>Item Three</TabContainer>
</SwipeableViews>
{
  fabs.map((fab, index) => (
    <Zoom>
      <Fab>{fab.icon}</Fab>
    </Zoom>
  ));
}

У меня есть что-то вроде:

<SwipeableViews>
  <TabContainer dir={theme.direction}>
    <ListOfThingsComponent />
  </TabContainer>
  <TabContainer dir={theme.direction}>Item Two</TabContainer>
  <TabContainer dir={theme.direction}>Item Three</TabContainer>
</SwipeableViews>
{
  fabs.map((fab, index) => (
    <Zoom>
      <Fab onClick={ListOfThingsComponent.Add???}>
        Add Item to List Component
      </Fab>
    </Zoom>
  ));
}

У моего ListOfThingsComponent изначально был AddКнопка, и она работала отлично.Но я хотел следовать подходу FAB, как это было в документах.Для этого кнопка «Добавить» будет находиться за пределами дочернего компонента.Итак, как мне получить кнопку от родителя для вызова метода Add дочернего компонента?

Я не уверен, как на самом деле реализовать обработчик события click для добавления элемента в список, если мой компонент списка находится внутривкладка, в то время как FAB находится за пределами всей структуры вкладок.

Насколько я знаю, я могу либо:

  1. найти способ соединить родителя / потомка для передачи обработчика событийчерез уровни (например, Как передать обработчик событий дочернему компоненту в React )
  2. найти способ лучше составить компоненты / иерархию, чтобы перевести ответственность на правильный уровень (например, удалитькомпонент и поместите его в тот же файл с this в области видимости, используя функциональные компоненты?)

Я видел, как люди используют ref, но это просто кажется хакерским.Я хотел бы знать, как это должно быть сделано в React.Было бы неплохо, если бы этот пример пошел немного дальше и показал, где должна находиться обработка событий для FAB.

Заранее спасибо, как всегда, я опубликую то, что я в итоге делаю

1 Ответ

1 голос
/ 13 марта 2019

Это зависит от того, что вы ожидаете от кликов.Будут ли они только изменять состояние данного элемента или будут выполнять изменения вне этой иерархии?Присутствует ли потрясающий эффект в каждой вкладке, или вы не уверены?

Я думаю, что в большинстве случаев вам лучше делать то, что вы делали раньше.Напишите CustomComponent для каждой вкладки и пусть он обрабатывает FAB самостоятельно.Единственный случай, когда это может быть плохим подходом, - это если вы заранее знаете, что обратный вызов FAB будет вносить изменения в иерархию CustomComponent и выходить из нее, потому что в этом случае вы можете в конечном итоге получить беспорядок обратного вызова в долгосрочной перспективе (тем не менее,ничего, что глобальное управление состоянием не могло исправить).

Редактировать после редактирования: В React невозможно вызвать функцию, находящуюся внутри дочернего компонента, без примененияRefs или другие механизмы, которые полностью избегают React) из-за одностороннего потока данных.Эта функция должна быть где-то общей, в данном случае в компоненте, который монтирует кнопку и компонент ListOfThings.Кнопка вызовет тот метод, который изменит состояние в компоненте «Родитель», и новое состояние будет передано в компонент ListOfThings через реквизиты:

export default class Parent extends Component {
  state = {
    list: []
  };

  clickHandler = () => {
    // Update state however you need
    this.setState({
      list: [...this.state.list, 'newItem']
    });
  }

  render() {
    return (
      <div>
        <SwipeableViews>
          <TabContainer dir={theme.direction}>
            <ListOfThingsComponent list={this.state.list /* Passing the state as prop */}/>
          </TabContainer>
          <TabContainer dir={theme.direction}>Item Two</TabContainer>
          <TabContainer dir={theme.direction}>Item Three</TabContainer>
        </SwipeableViews>
        {
          fabs.map((fab, index) => (
            <Zoom>
              <Fab onClick={this.clickHandler /* Passing the click callback */}> 
                Add Item to List Component
              </Fab>
            </Zoom>
          ))
        }
      </div>
    )
  }
}

Если вам действительно нужна ваша иерархия, чтобы оставаться такой, вы должны использовать этот метод или какую-либо форму глобального управления состоянием, из которой ListOfThingsComponent может читать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...