Как передать состояние родительскому компоненту при щелчке на ссылке "Реакция-маршрутизатор"?

Я хочу создать одностраничное приложение, которое работает с переходами, которое будет выглядеть следующим образом:

*------*--------------*-----------*
|      |              |           |
| Shop | Landing Page | Biography |
|      |              |           |
*------*--------------*-----------*
|                                 |
|          Contact page           |
|                                 |
*---------------------------------*

По сути, когда вы впервые заходите на сайт, вы попадаете на экран посадки. Оттуда доступны 3 ссылки: "Биография", "Магазин" и "Контакт" ("Контакт" доступен на трех "верхних" страницах).

После того, как вы щелкнете по ссылке, чтобы перейти в "Магазин" или "Биография", вы можете вернуться на посадку или перейти на страницу контактов, но вы не можете перейти на "противоположную" страницу (отсюда и схему). Кроме того, когда вы перейдете на страницу контактов и нажмете "назад", вы попадете на последнюю страницу, на которой вы были раньше.

Я создал CodeSandBox, чтобы избежать вставки полкилометра кода, который не обязательно имеет к этому какое-либо отношение, но все еще немного обеспокоен

Поэтому я хотел бы иметь возможность точно настроить свои переходы, например, переходя слева направо при переходе в "Биография" (и наоборот при выходе), справа налево при переходе в "Магазин" и снизу вверх при переходе в контактная форма.

После прочтения множества вопросов и документации о react-transition-groupУ меня была идея сделать что-то вроде этого:

// src/App.js
const PageFade = props => (
  // props.transition would contain "topBottom", "bottomTop", "leftRight" and "rightLeft" 
  // (so that I would ajust my CSS in consequence)
  {props.transition === 'topBottom' &&
  <CSSTransition
    {...props}
    classNames={props.transition !== null && props.transition}
    timeout={1000}
    mountOnEnter={true}
    unmountOnExit={true}
  />
  }
);
}

Я мог бы сделать это или создать <CSSTransition /> для каждой возможности я действительно не знаю.

Моя проблема в том, что мне нужно сказать это <CSSTransition /> или то, что было нажато, или (лучше), какой переход нужно отобразить.

Для этого я попытался установить transition состояние, но похоже, что оно слишком сильно обновляется, и мои знания о React устарели, и я не знаю, как справиться со всем этим с помощью response-route.

Обновить

Спасибо всем за ваши ответы, и извините за то, что не отвечаете быстрее, мой компьютер замирает от безумия.

Итак, я создал новый класс CSSTransitions где я скопировал / вставил ответ @ brandon, адаптируя его под свои нужды. Однако у меня есть проблема с componentWillReceiveProps(nextProps), поскольку он nextProps.location имеет значение null, каким-то образом контекст реагирующего маршрутизатора не передается.

Я обновил свой CodeSandBox, CSSTransitions класс находится в каталоге 'utils' внутри каталога 'src'.

Еще раз спасибо за ваши ответы

заранее спасибо

2 ответа

Решение

Мое предложение состоит в том, чтобы ваш компонент PageFade отслеживал маршруты и сравнивал предыдущий маршрут с новым маршрутом и изменял его направление на основе изменения маршрутов. Вот грубый пример:

import {withRouter} from 'react-router';

const directions = {
  "/->/contact": "top-bottom",
  "/contact->/": "bottom-top",
  // etc...
}

class PageFadeDumb extends React.Component {
  state = {direction: "top-bottom"};

  componentWillReceiveProps(nextProps) {
    if (nextProps.location.pathname !== this.props.location.pathname) {
      const transitionPath = `${this.props.location.pathname}->${nextProps.location.pathname}`;
      const newDirection = directions[transitionPath] || "top-bottom";
      console.log(`newDirection = ${newDirection}`);
      this.setState({direction: newDirection});
    }
  }

  render() {
    const direction = this.state.direction;
    // use here somehow?
    return (
      <CSSTransition
        {...(this.props)}
        classNames="fadeTranslate"
        timeout={1000}
        mountOnEnter={true}
        unmountOnExit={true}
      />
    );
  }
}

const PageFade = withRouter(PageFadeDumb);

Я бы сделал это так:

class ParentComponent extends React.Component {

  state = {
    some_state: ""
  }

  myCallback = (ev) => {
    this.setState({ some_state: ev.target.dataset.mydata });
  }

  render() {
    <ChildComponent cback={this.myCallback} />  // Insert all other props too
  }

}

class ChildComponent extends React.Component {

  render() {
    <button data-mydata="Value you need to pass up" onClick={this.props.cback}>
      Click me
    </button>
  }

}

Когда кнопка нажата, обратный вызов, определенный в ParentComponent запускается и получает объект Event, а затем вы можете захватить одно или несколько значений, используя атрибуты данных.

Чтобы узнать больше об этих data- атрибуты и HTMLElement.dataset Вы можете прочитать это.

Другие вопросы по тегам