Создайте компонент React из строки с заполнителями - PullRequest
0 голосов
/ 30 мая 2020

Мне нужно динамически построить компонент React на основе последовательно структурированного текста в неизвестном порядке. Как мне заменить номера заполнителей (определенные согласованным образом, см. Ниже) соответствующими компонентами, которые используют заполнители как реквизиты?

const text = "some (1) arbitrary amount of [2] text";

return (
  <div>
    some
    <Component1 var={1} />
    arbitrary amount of 
    <Component2 var={2} />
    text
   </div>
)

Размещение и порядок [] и () не согласованы, так что:

const text = "[2] some arbitrary amount (1) of text";

return (
  <div>
    <Component2 var={2} />
    some arbitrary amount
    <Component1 var={1} />
    of text
   </div>
)

Ответы [ 3 ]

1 голос
/ 30 мая 2020

Да, возможно, вы могли бы сделать что-то вроде этого

  const C1 = () => " C1 ";
  const C2 = () => " C2 ";
  const dynamics = { // the ids of these dynamic components that will be used as placeholders
    1: C1,
    2: C2
  };
  const text = "some (1) arbitrary amount of [2] text";
   // you may want to customize this function to suit your needs
  const isDynamic = src => {
    return (
      (src[0] === "(" && src[src.length - 1] === ")") ||
      ("[" && src[src.length - 1] === "]")
    );
  };
  const components = text.split(" ");

// dont forget to add a key to the mapped components, but i will leave this to you, since i dont have all the requirements about the dynamic components, and whether there might be duplicates
  return (
    <div >
      {components.map(comp => {

        if (isDynamic(comp)) {
          const dynamicCompId = parseInt(
            comp
              .split("")
              .filter(x => !Number.isNaN(+x))
              .join("")
          );
          const Dynamic = dynamics[dynamicCompId];
          return <Dynamic   />;
        }
        return comp;
      })}
    </div>
  );
1 голос
/ 30 мая 2020

Это немного сложно, для упрощения мы заменяем только один заполнитель (1):

const App = () => {
  return <div>{splitAndRender(text, `(1)`, Component1)}</div>;
};

Где splitAndRender может быть реализовано как:

const splitAndRender = (text, regex, Component) => {
  const splitByRegex = text.split(regex);
  return splitByRegex.reduce((acc, curr, index) => {
    const isLastItem = index === splitByRegex.length - 1;
    return [...acc, curr, isLastItem ? null : <Component key={index} />];
  }, []);
};

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

Edit mystifying-thompson-j9e2m

0 голосов
/ 04 июля 2020

Я придумал этот простой и эффективный метод, который избавляет от необходимости выполнять вложенные / итерационные циклы по мере увеличения количества игл:

// Function to split string on multiple needles, keeping needles in place
function splitMulti(str, needles) {
  let out = str.valueOf()
  for (var i = 0; i < needles.length; i++) {
    out = out.replace(needles[i], `SPLITDELIN${needles[i]}SPLITDELIN`);
  }
  out = out.split('SPLITDELIN');
  return out;
}


function buildChildren(string){
  // string = "some (1) arbitrary amount of [2] text";

  
  const needles = [
    "(1)",
    "[2]",
  ];

  const childArray = splitMulti(string, needles);

  childArray.forEach((item, index, array) => {
    switch (item) {
      case "(1)":
        array[index] = <Component1 var={1} />
        break;
      case [2]:
        array[index] = <Component2 var={2} />
        break;
    }
  });

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