Как я могу включить параметры URL при программной навигации с использованием API истории (не ссылок)? - PullRequest
0 голосов
/ 19 января 2020

У меня есть веб-приложение, в котором я хотел бы ввести параметры URL <: param> для реализации схемы URL. Для навигации я использую History API для добавления sh новых URL-адресов в стек истории.

  1. Моя первая цель - запросить параметр: query в ' / category? query =: query '
  2. Мой второй объект - ограничить это 1 или более символами (. +)

Я пробовал это несколькими различными способами:

const OLD_PATHS = {
  CATEGORY_PAGE     : '/category',
  CATEGORY_PAGE_TAB : '/category/:subcategory'
}

const NEW_PATHS = {
  CATEGORY_PAGE_BASE: '/category',
  CATEGORY_PAGE     : '/category?query=:query',
  CATEGORY_PAGE_TAB : '/category/:subcategory?query=:query'
};

searchCategoryV1() {
  this.props.history.push({
      pathname: OLD_PATHS.CATEGORY_PAGE,
      search: `?query=${encodeURIComponent(this.state.query)}`,
      state: {query: this.state.query }
  });
}

searchSubCategoryV1() {
  this.props.history.push({
      pathname:  OLD_PATHS.CATEGORY_PAGE += `/${searchCategory}`,
      search: `?q=${encodeURIComponent(this.state.query)}`,
      state: { query: this.state.query }
  });

searchCategoryV2() {
  this.props.history.push(
    _.replace(NEW_PATHS.CATEGORY_PAGE, ":query", this.state.query),
    {query: this.state.query}
  );
}

searchSubCategoryV2(subcategory) {
  this.props.history.push(
    `${NEW_PATHS.CATEGORY_PAGE_BASE}/${subcategory}?query=${this.state.query}`,
    {query: this.state.query}
  );
}

Когда я не пытаюсь применить схему URL, я могу программно перемещаться. Однако, попытка потребовать параметр 'query' не привела к тому, что этот маршрут работает! Пожалуйста, помогите мне понять, что делать здесь, это будет высоко ценится!

1 Ответ

1 голос
/ 20 января 2020

Я не уверен на 100%, что понимаю ваше намерение, но, возможно, это может сработать ... где это позволяет вам добавлять / удалять запросы вручную через взаимодействие с пользователем и / или путем навигации по истории браузера (мышь назад и вперед) , Также будут сохраняться запросы при обновлении страницы.

Если вам абсолютно необходимо использовать опцию params, я бы поместил ее в path Маршрута и получил к ней доступ через (this.props.)location.params. Если его необходимо динамически заменить, лучше переместить его в параметры запроса, например: /movies/action?subcategory=comedy&year=2019&starring=Bob%20Saget. Когда вы начинаете менять параметры, структура вашего маршрута может оказаться излишне загроможденной и трудной для управления.

Примечания. В этом примере qs используется для анализа (this.props.)location.search простой строки и объекта. запросов. Кроме того, он также использует рендерный реквизит (см., Например, pages/Homes/index.js) для передачи родительского state ребенку как props через function.

* 1020. * Демо :

https://c7isk.csb.app/

Источник :

Edit RRD - Query Filters


компоненты / QueryHandler

import { PureComponent } from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router-dom";
import { setQuery, stringifyQuery } from "../../utils";

class QueryHandler extends PureComponent {
  state = setQuery(this.props.location.search);

  static getDerivedStateFromProps = ({ location }) => setQuery(location.search);

  pushToLocation = query =>
    this.props.history.push(`${this.props.location.pathname}?${query}`);

  updateQuery = nextQuery =>
    this.pushToLocation(
      stringifyQuery({
        ...this.state.queries,
        ...nextQuery
      })
    );

  clearFilters = () => this.props.history.push(this.props.location.pathname);

  render = () =>
    this.props.children({
      ...this.state,
      clearFilters: this.clearFilters,
      updateQuery: this.updateQuery
    });
}

QueryHandler.propTypes = {
  children: PropTypes.func.isRequired,
  history: PropTypes.shape({
    push: PropTypes.func.isRequired
  }),
  location: PropTypes.shape({
    pathname: PropTypes.string,
    search: PropTypes.string
  })
};

export default withRouter(QueryHandler);

компоненты / фильтры

import React, { PureComponent } from "react";
import PropTypes from "prop-types";

class Filters extends PureComponent {
  handleChange = ({ target: { name, value } }) => {
    this.props.updateQuery({ [name]: value });
  };

  clearQuery = name => {
    this.props.updateQuery({ [name]: null });
  };

  render = () => {
    const currentQuery = {
      eventdate: "",
      eventtype: "",
      teamid: "",
      ...this.props.queries
    };

    return (
      <div style={{ margin: "0 auto", width: 500 }}>
        <div className="filter-container">
          <label className="label" htmlFor="eventdate">
            Event Date:
          </label>
          <input
            className="uk-input"
            name="eventdate"
            type="date"
            value={currentQuery.eventdate}
            onChange={this.handleChange}
          />
          {currentQuery.eventdate && (
            <button
              className="uk-button uk-button-danger"
              type="button"
              onClick={() => this.clearQuery("eventdate")}
            >
              X
            </button>
          )}
        </div>
        <div className="filter-container">
          <label className="label" htmlFor="eventtype">
            Event Type:
          </label>
          <select
            name="eventtype"
            value={currentQuery.eventtype}
            className="uk-select"
            onChange={this.handleChange}
          >
            <option value="" disabled hidden>
              Select your option
            </option>
            <option value="game">Game</option>
            <option value="practice">Practice</option>
            <option value="promo">Promo</option>
          </select>
          {currentQuery.eventtype && (
            <button
              className="uk-button uk-button-danger"
              type="button"
              onClick={() => this.clearQuery("eventtype")}
            >
              X
            </button>
          )}
        </div>
        <div className="filter-container">
          <label className="label" htmlFor="teamid">
            Team ID:
          </label>
          <input
            className="uk-input"
            name="teamid"
            type="number"
            min="0"
            value={currentQuery.teamid}
            placeholder="Select a team ID..."
            onChange={this.handleChange}
          />
          {currentQuery.teamid && (
            <button
              className="uk-button uk-button-danger"
              type="button"
              onClick={() => this.clearQuery("teamid")}
            >
              X
            </button>
          )}
        </div>
        <div style={{ textAlign: "center" }}>
          <button
            className="uk-button uk-button-primary"
            type="button"
            onClick={this.props.clearFilters}
          >
            Clear All Filters
          </button>
        </div>
      </div>
    );
  };
}

Filters.propTypes = {
  queries: PropTypes.shape({
    eventdate: PropTypes.string,
    eventtype: PropTypes.string,
    teamid: PropTypes.string
  }),
  updateQuery: PropTypes.func.isRequired
};

export default Filters;

утилит / index. js

import qs from "qs";

/**
 * Stringifies an object of query properties.
 *
 * @function stringifyQuery
 * @param {object} query
 * @returns {string}
 */
export const stringifyQuery = query => qs.stringify(query, { skipNulls: true });

/**
 * Parses a stringified query to an object of queries.
 *
 * @function parseQuery
  @param {string} query
 * @returns {object} - An object of query properties.
 */
export const parseQuery = query =>
  qs.parse(query, {
    ignoreQueryPrefix: true
  });

/**
 * Utilizes the functions above to parse and stringify a query.
 *
 * @function setQuery
 * @param {string} query
 * @returns {object}
 */
export const setQuery = query => {
  const queries = parseQuery(query);
  const queryString = stringifyQuery(queries);

  return { queries, queryString };
};

страниц / Home

import React from "react";
import QueryHandler from "../../components/QueryHandler";
import Filters from "../../components/Filters";

function Home() {
  return (
    <div className="home">
      <QueryHandler>
        {props => (
          <>
            <Filters {...props} />
            <pre style={{ background: "#ebebeb" }}>
              <code>{JSON.stringify(props, null, 4)}
            
)} ); } экспорт по умолчанию Home;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...