Функция более высокого порядка - недопустимый тип элемента: ожидаемая строка или класс / функция, но полученный объект - PullRequest
2 голосов
/ 20 апреля 2020

Я работаю над учебником (https://www.johnstewart.dev/firebase-auth-react-mobx/), играя с Mobx, React и Auth. Однако я получаю это сообщение об ошибке

Ошибка: недопустимый тип элемента: ожидается строка (для встроенных компонентов) или класс / функция (для составных компонентов), но есть: объект. Проверьте метод рендеринга Context.Consumer.

, который, как я подозреваю, связан со следующим кодом. Это подразумевается как функция более высокого порядка, которая упаковывает компоненты в маршрутизаторе для проверки состояния аутентификации.

import React from "react";
import authStore from "../../store/authStore";
import { Redirect } from "react-router-dom";

const protectedRoute = (RouteComponent) => {
  if (authStore.loggedIn) {
    return RouteComponent;
  }
  return <Redirect to="/login" />;
};

export default protectedRoute;

Завернутый компонент в приложении. js выглядит так:

<Route path="/register" component={protectedRoute(Register)} />

Я рассуждаю так: когда я вручную изменяю свой authStore.loggedIn на true, все проходит отлично. Однако, когда я устанавливаю для authStore.loggedIn значение false, появляется ошибка.

Без сомнения, это что-то безумно простое в Redirect, но поиск в стеке не очень полезен, да и сеть в целом. Любые предложения ??

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

import React, { useEffect, useState } from "react";
import { inject, observer } from "mobx-react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faPlusSquare } from "@fortawesome/free-solid-svg-icons";
import BootstrapTable from "react-bootstrap-table-next";
import filterFactory, {
  textFilter,
  selectFilter,
} from "react-bootstrap-table2-filter";
import rp from "request-promise";

import Spinner from "../layout/Spinner";

const Register = (props) => {
  const [dataLoaded, setdataLoaded] = useState(false);

  useEffect(() => {
    rp.get({
      uri: "http://localhost:5050/api/risk",
      json: true,
      headers: {
        "User-Agent": "Request-Promise",
      },
    })
      .then((risks) => {
        props.riskStore.riskList = risks;
        console.log("Risks successfully loaded.");
        setdataLoaded(true);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  const rowEvents = {
    onClick: (e, row, rowIndex) => {
      props.history.push(`/risk/${row._id}`);
    },
  };

  return dataLoaded ? (
    <div>
      <br />
      <h1 className="register-heading">Risk Register</h1>
      <div className="row">
        <div className="col-md-4">
          <p className="register-text">
            Please use the column headings to sort the register. To add a new
            task, click the button to the right.
          </p>
        </div>
        <div className="col-md-6"></div>
        <div className="col-md-2">
          <button
            className="btn btn-primary"
            onClick={() => props.history.push("/risk/new")}
          >
            <FontAwesomeIcon icon={faPlusSquare} /> New Task
          </button>
        </div>
      </div>

      <BootstrapTable
        keyField="id"
        data={props.riskStore.riskList}
        columns={risksColumns}
        filter={filterFactory()}
        filterPosition="top"
        striped={true}
        hover={true}
        condensed={true}
        rowEvents={rowEvents}
        bootstrap4={true}
      />
    </div>
  ) : (
    <Spinner />
  );
};

const selectOptions = {
  true: "Archived",
  false: "Active",
};

const archiveFormatter = (cell, row, rowIndex, colIndex) => {
  if (cell === true) {
    return <span>Archived</span>;
  } else {
    return <span>Active</span>;
  }
};

const risksColumns = [
  {
    dataField: "_id",
    text: "",
    hidden: true,
  },
  {
    dataField: "riskName",
    text: "Risk",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { width: "31%" };
    },
  },
  {
    dataField: "riskCategoryBroad.value",
    text: "Broad Risk Category",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { textAlign: "center" };
    },
    align: "center",
  },
  {
    dataField: "riskCategoryNarrow.value",
    text: "Narrow Risk Category",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { textAlign: "center" };
    },
    align: "center",
  },
  {
    dataField: "riskOfficerPrimary.value",
    text: "Responsible Officer (Primary)",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { width: "20%", textAlign: "center" };
    },
    align: "center",
  },
  {
    dataField: "grossRiskAssessment.grossRiskRating.label",
    text: "Gross Risk Rating",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { textAlign: "center" };
    },
    align: "center",
  },
  {
    dataField: "netRiskAssessment.netRiskRating.label",
    text: "Net Risk Rating",
    filter: textFilter(),
    sort: true,
    headerStyle: (column, colIndex) => {
      return { textAlign: "center" };
    },
    align: "center",
  },
  {
    dataField: "archived",
    text: "Archived",
    sort: true,
    filter: selectFilter({ options: selectOptions }),
    headerStyle: (column, colIndex) => {
      return { textAlign: "center", width: "8%" };
    },
    formatter: archiveFormatter,
    align: "center",
  },
];

export default inject("riskStore")(observer(Register));

1 Ответ

1 голос
/ 20 апреля 2020

Функция rpotectedRoute возвращает различные типы в зависимости от того, вошли ли вы в систему.

  1. Когда authStore.loggedIn имеет значение true, возвращает React Component , это что-то вроде (props) => <jsx/>
  2. , когда auth.loggedIn ложно, возвращается Элемент реагирования , это что-то вроде <jsx/>

Так что в этом случае вы должны сделать

import React from "react";
import authStore from "../../store/authStore";
import { Redirect } from "react-router-dom";

const protectedRoute = (RouteComponent) => {
  if (authStore.loggedIn) {
    return RouteComponent;
  }
  return () => <Redirect to="/login" />;
};

export default protectedRoute;

Если вы новичок в реакции, я рекомендую вам прочитать Реагировать на компоненты, элементы и экземпляры

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