Как получить текстовый элемент данного компонента react в React.cloneElement?

#javascript #reactjs #locale #globalization

Вопрос:

Разработчики дают мне заголовки таблицы:

 const CustomersTable = () =gt; {   var headers=lt;gt;  lt;thgt;Namelt;/thgt;  lt;thgt;Agelt;/thgt;  lt;thgt;Another textlt;/thgt;  lt;/gt;   return lt;Table  headers={headers}  /gt; }   

И это код Table компонента:

 const Table = ({headers}) =gt; {   var clonedHeaders = React.Children  .toArray(headers.props.children)  .map(header =gt; React.cloneElement(header, {  className: "text-gray-900 py-3 font-light text-xs"  }));   return lt;tablegt;  lt;theadgt;  lt;trgt;  {clonedHeaders}  lt;/trgt;  lt;/theadgt;  lt;/tablegt; }  

Я могу использовать React.cloneElement для добавления атрибутов к элементам, которые я получаю в качестве реквизитов моего компонента.

Однако я также хочу иметь возможность изменять текстовое содержимое этих полученных элементов.

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

 var headers = lt;gt;  lt;thgt;{t('Name')}lt;/thgt;  lt;thgt;{t('Age')}lt;/thgt;  lt;thgt;{t('Other text')}lt;/thgt; lt;/gt;  

Я хочу централизовать эту функцию для всех пользователей. t(text) headers Могу я это сделать?

Ответ №1:

Вы можете использовать ту же технику для дочерних элементов заголовков, что и для самих заголовков:

 const clonedHeaders = React.Children  .toArray(headers.props.children)  .map(header =gt; React.cloneElement(header, {  className: "text-gray-900 py-3 font-light text-xs",  children: React.Children.toArray(header.props.children).map(child =gt; {  return typeof child === "string" ? t(child) : child;  })  }));  

Живой Пример:

 const {useState} = React;  function t(english) {  // Just so we can see that it happens  return english.toLocaleUpperCase(); }  const CustomersTable = () =gt; {   var headers=lt;React.Fragmentgt;  lt;thgt;Namelt;/thgt;  lt;thgt;Agelt;/thgt;  lt;thgt;Another textlt;/thgt;  lt;/React.Fragmentgt;;   return lt;Table  headers={headers}  /gt;; };  const Table = ({headers}) =gt; {   const clonedHeaders = React.Children  .toArray(headers.props.children)  .map(header =gt; React.cloneElement(header, {  className: "text-gray-900 py-3 font-light text-xs",  children: React.Children.toArray(header.props.children).map(child =gt; {  return typeof child === "string" ? t(child) : child;  })  }));   return lt;tablegt;  lt;theadgt;  lt;trgt;  {clonedHeaders}  lt;/trgt;  lt;/theadgt;  lt;/tablegt;; };  ReactDOM.render(lt;CustomersTable /gt;, document.getElementById("root")); 
 lt;div id="root"gt;lt;/divgt;  lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"gt;lt;/scriptgt; lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"gt;lt;/scriptgt; 

Этот пример не выполняет никакой рекурсии, поэтому он не будет обрабатываться lt;thgt;lt;span className="something"gt;Namelt;/spangt;lt;/thgt; . Если вы хотите справиться с этим, вам придется написать рекурсивную функцию, чтобы справиться с этим, но это будет в том же духе.

Комментарии:

1. Это был один из самых приятных ответов, которые я видел в своей жизни. Легко и очень практично. Мне удалось глобализировать заголовки более чем 100 таблиц за 5 минут, а не за недели. Огромное спасибо.