Каков наиболее эффективный способ рендеринга вложенного объекта n-уровня в React JS? - PullRequest
2 голосов
/ 18 октября 2019

У меня есть данные, поступающие из API следующим образом:

{
  "expression": [
    "a",
    "b"
  ],
  "groups": [
    {
      "expression": [

      ],
      "groups": [
        {
          "expression": [
            "c",
            "d"
          ],
          groups: null
        }
      ]
    },
    {
      "expression": [
        "p",

      ],
      groups: null
    }
  ]
}

Я должен рендерить выражения и группы (включая выражения и несколько групп). Строительный блок является выражением. Нам нужно отображать вложенные выражения в виде групп.

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

Вот что-то похожее на мою пробную версию -

let conditionStack = [];
  function parseInnerConditions(conditionObj) {
    if (conditionObj.expression) {
      conditionObj.expression.map((each, index) => {
        conditionStack = [
          ...conditionStack,
          <NewExpression key={index} conditionExpression={each} />, //renders an expression
        ];
      });
    }
    if (conditionObj.groups && conditionObj.groups.length) {
      return conditionObj.groups.map((child, index) => {
        conditionStack = [
          ...conditionStack,
          <ConditionGroup key={index}> // renders a block or group of expressions
            {parseInnerConditions(child)}
          </ConditionGroup>,
        ];
      });
    }
    return conditionStack;
  }

  return (
    <div>
    parseInnerConditions(conditionObject)
    </div>
  )

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

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

  1. Expression Для простого рендеринга выражения в группе.
  2. Group Для рендеринга группы.
  3. Groups Для извлечения и последующего рендеринга компонента Group для дальнейших групп в ваших данных.

Вот пример кода:

Index.js Этот файл получает данные из API.

import React from "react";
import Group from "./Group";

const data = {
  expression: ["a", "b"],
  groups: [
    {
      expression: [],
      groups: [{ expression: ["c", "d"], groups: null }]
    },
    {
      expression: [],
      groups: [
        { expression: ["e", "f"], groups: null },
        { expression: ["g", "h"], groups: null }
      ]
    },
    {
      expression: ["p"],
      groups: null
    }
  ]
};
const stage = 1;
const Main = () => {
  return (
    <div>
      <Group data={data} stage={stage} />
    </div>
  );
};

export default Main;

Group.js Для рендеринга группы.

import React from "react";
import Expression from "./Expressions";
import Groups from "./Groups";

const populateGroup = (data, stage) => {
  const HTML = [];
  for (const x in data) {
    if (x === "expression") {
      HTML.push(<Expression expression={data[x]} />);
    }
    if (x === "groups") {
      HTML.push(<Groups data={data[x]} stage={stage} />);
    }
  }
  return HTML;
};

const Group = ({ data, stage }) => {
  return (
    <div>
      <p>{`Group @ Stage ${stage}`}</p>
      <ol className="Group">{populateGroup(data, stage + 1).map(el => el)}</ol>
    </div>
  );
};

export default Group;

Expression.js Для простого рендеринга выражения в группе.

import React from "react";

const Expression = ({ expression }) => {

return (
    <div className="expression">
      {expression.map(term => (
        <h3 style={{ display: "inline" }}>{term}</h3>
      ))}
    </div>
  );
};

export default Expression;

Groups.js Для извлечения и последующего рендеринга Group компонента.

import React from "react";
import Group from "./Group";

const Groups = ({ data, stage }) => {

  if (data === null) return <span></span>;

  return (
    <div className="GroupsSection">
      {data.map((section, i) => (
        <Group key={i} data={section} stage={stage} />
      ))}
    </div>
  );
};

export default Groups;

Производительность При таком подходе на основе компонентов данные разделяются на части, что должно повысить производительность для еще лучших результатов. for...in и map можно заменить на петлю for. Пример визуализации

1 голос
/ 18 октября 2019

Ваш обратный вызов map() не имеет значения return, но во втором операторе if вы возвращаете массив, поэтому в результате вы получите [undefined, undefined, ...] при повторном обращении к каждому groups.

Чтобы исправить решение, измените оба значения .map() на .forEach() и удалите ключевое слово return до conditionObj.groups.map(...).

Хотя есть и лучший подход:

function ConditionGroup ({ expression, groups }) {
  const conditionExpressions = useMemo(
    () => expression && expression.map(
      (value, index) => (
        <NewExpression key={index} conditionExpression={value} />
      )
    ),
    [expression]
  );
  const conditionGroups = useMemo(
    () => groups && groups.map(
      (value, index) => (
        <ConditionGroup key={index} {...value} />
      )
    ),
    [groups]
  );

  return (
    <div>
      {conditionExpressions}
      {conditionGroups}
    </div>
  );
}

Обратите внимание, что использование index в качестве клавиши является антипаттерном . В идеале, вы захотите использовать уникальный идентификатор, если он вам предоставлен. См. ReactJS: Каков наилучший способ предоставления ключей в элементе массива для получения дополнительной информации об этом.

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