Как отобразить компонент React Route на совершенно новой, пустой странице - PullRequest
1 голос
/ 02 июня 2019

Я пытаюсь отобразить страницу печати с помощью React Router.Итак, у меня есть два компонента:

export default class PurchaseOrder extends React.Component{
....
render(){
   const {orderDate, client} = this.state.order;
   //omitted for brevity
    return(
            <BrowserRoute>
              <Button
                component={Link}
                to="/order/print"
                target="_blank"
              >
                Print
              </Button>
              <Route
                path="/order/print"
                render={props => (
                  <OrderPrint
                    {...props}
                    orderDate={orderDate}
                    client={client}
                  />
                )}
              />
            </BrowserRoute>

   }
}

И OrderPrint:

export default function OrderPrint(props) {
  return (
    <div>props.orderDate</div>
    <div>props.client.name</div>
  );
}

Как вы видите, я пытаюсь представить печатную версию заказа на покупку одним щелчком мыши.кнопка.Компонент OrderPrint отображается, но отображается прямо под кнопкой.Я мог бы поместить Route в свой корневой компонент, которым является App, таким образом, убедившись, что я получаю только содержимое компонента OrderPrint, отображаемого так:

class App extends Component {
render() {
  return (
    <div className="App">
      <Router>
        <Route exact path="/" component={PurchaseOrder} />
        <Route exact path="/order/print" component={OrderPrint} />
      </Router>
    </div>
  );
}

}

Но вв этом случае я не смогу передать ему необходимые реквизиты.Таким образом, в данном конкретном случае, как заменить все содержимое страницы содержимым компонента OrderPrint и при этом иметь возможность передавать в него необходимые входные данные?

Обновление

Как упомянуто в комментариях @Akalanka Weerasooriya, я мог бы сохранить все состояние в компоненте приложения.Но одна вещь помешала мне сделать это: это означает, что мне практически всегда придется использовать опору render компонента Route вместо опоры component.Хорошо, это не проблема, но если это путь, то почему документация React Router почти всегда использует шаблон

<Route path="/about" component={About} /> 

в качестве стандартного способа его использования?Напомним, что если я пойду по пути Единого Истины и сохраню все свое состояние в одном месте, то не значит ли это, что я всегда буду использовать

<Route path="/about" render={props=>(<div>props.someProp</div>)} />

Я не говорю, что естьпроблема с этим, он просто упоминает об этом в документации только после того, как шаблон component={SomeComponent} смущает меня.

Ответы [ 2 ]

1 голос
/ 02 июня 2019

здесь у вас есть PrivateRoute, который представляет собой пользовательский маршрут, который содержит заголовок, а заголовок отображается только в маршрутах PrivateRoute, поэтому при попытке перейти к новому маршруту, например path="/order/print", вы не получите заголовок, которыйимеет кнопку в нем.

function Header(props) {
  return (
    <div>
      <Button
        component={Link}
        to="/order/print"
        target="_blank">
         Print</Button>
      {props.children}
    </div>
  )
}

const PrivateRoute = ({ component: Component, layout: Layout, ...rest }) => {
  return <Route {...rest} render={props => {
    return <Layout>
      <Component {...props} />
    </Layout>
  }} />
}


export default class PurchaseOrder extends React.Component{

render(){
   const {orderDate, client} = this.state.order;
   //omitted for brevity
    return(
            <BrowserRouter>
              <div>
               <PrivateRoute exact path="/" layout={Header} component={Landing} />

              <Route
                path="/order/print"
                render={props => (
                  <OrderPrint
                    {...props}
                    orderDate={orderDate}
                    client={client}
                  />
                )}
              />
              </div>
            </BrowserRouter>

   }
}
1 голос
/ 02 июня 2019

Не знаю, зачем вам нужен другой маршрут для печати страницы, но в любом случае, если вы хотите использовать его на новой пустой странице, вы можете воспользоваться функцией ReactDOM.createPortal .
Вы можетесоздайте новую страницу и / или даже новое окно, используя window.open, поддерживая синхронизацию потока реагирующих данных.

Вот пример работы портала в новом окне с обновлениями текущего состояния от компонента, который запустил это окно с помощью портала:

пример выполнения , i 'm разделяет внешний фрагмент и не использует здесь фрагменты стека, потому что window.open возвращает null в контексте фрагментов стека

Исходный код:

class WindowPortal extends React.PureComponent {
  containerEl = document.createElement("div");
  externalWindow = null;

  componentDidMount() {
    const { width = 450, height = 250, left = 150, top = 150 } = this.props;
    const windowFetures = `width=${width},height=${height},left=${left},top=${top}`;
    this.externalWindow = window.open("", "", windowFetures);
    this.externalWindow.document.body.appendChild(this.containerEl);
  }

  componentWillUnmount() {
    this.externalWindow.close();
  }

  render() {
    return ReactDOM.createPortal(this.props.children, this.containerEl);
  }
}

class App extends React.PureComponent {
  state = {
    counter: 0,
    showWindowPortal: false
  };

  componentDidMount() {
    window.setInterval(() => {
      this.setState(state => ({
        counter: state.counter + 1
      }));
    }, 1000);
  }

  toggleWindowPortal = () => {
    this.setState(state => ({
      ...state,
      showWindowPortal: !state.showWindowPortal
    }));
  };

  closeWindowPortal = () => {
    this.setState({ showWindowPortal: false });
  };

  render() {
    return (
      <div>
        <h1>Counter: {this.state.counter}</h1>

        <button onClick={this.toggleWindowPortal}>
          {this.state.showWindowPortal ? "Close the" : "Open a"} Portal
        </button>

        {this.state.showWindowPortal && (
          <WindowPortal closeWindowPortal={this.closeWindowPortal}>
            <h2>We are in a portal on a new window</h2>
            <h3>{`This is the current state: ${this.state.counter}`}</h3>
            <p>different window but sharing the state!!</p>

            <button onClick={() => this.closeWindowPortal()}>Close me!</button>
          </WindowPortal>
        )}
      </div>
    );
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...