Как зациклить и визуализировать элементы в React.js без массива объектов для сопоставления?

85

Я пытаюсь преобразовать компонент jQuery в React.js, и одна из вещей, с которыми я сталкиваюсь, - это рендеринг n числа элементов на основе цикла for.

Я понимаю, что это невозможно, или рекомендуется, и что там, где существует массив в модели, имеет смысл использовать map. Это прекрасно, но как насчет того, когда у вас нет массива? Вместо этого у вас есть числовое значение, которое приравнивается к заданному количеству элементов для рендеринга, то что вы должны делать?

Вот мой пример, я хочу префикс элемента с произвольным числом тегов span на его иерархическом уровне. Таким образом, на уровне 3, я хочу 3 тега span перед текстовым элементом.

В javascript:

for (var i = 0; i < level; i++) {
    $el.append('<span class="indent"></span>');
}
$el.append('Some text value');

Кажется, я не могу это получить, или что-то похожее на работу в компоненте JAX React.js. Вместо этого мне пришлось сделать следующее: сначала построим массив temp на нужную длину, а затем зациклируем массив.

React.js

render: function() {
  var tmp = [];
  for (var i = 0; i < this.props.level; i++) {
    tmp.push(i);
  }
  var indents = tmp.map(function (i) {
    return (
      <span className='indent'></span>
    );
  });

  return (
    ...
    {indents}
    "Some text value"
    ...
  );
}

Неужели это не может быть лучшим или единственным способом добиться этого? Что мне не хватает?

Теги:
react-jsx

4 ответа

159
Лучший ответ

Вместо этого вы можете использовать один цикл

var indents = [];
for (var i = 0; i < this.props.level; i++) {
  indents.push(<span className='indent' key={i}></span>);
}
return (
   <div>
    {indents}
    "Some text value"
   </div>
);

Вы также можете использовать .map и fancy es6

return (
   <div>
    {this.props.level.map((item, index) => (
       <span className='indent' key={index} />
    ))}
    "Some text value"
   </div>
);

Кроме того, вы должны обернуть возвращаемое значение в контейнер. Я использовал div в приведенном выше примере

Как говорится в документах здесь

В настоящее время в компоненте render вы можете вернуть только node; если у вас есть, скажем, список divs для возврата, вы должны обернуть ваши компоненты в div, span или любой другой компонент.

  • 1
    Это работает, и это намного проще, спасибо. Да, я знаю, что вы должны обернуть возвращаемое значение в контейнер, я уже делаю, что это просто отсутствует в примере.
  • 2
    добавить ключи внутри цикла. ключи важны в реакции.
Показать ещё 6 комментариев
42

Вот более функциональный пример с некоторыми функциями ES6:

'use strict';

const React = require('react');

function renderArticles(articles) {
    if (articles.length > 0) {      
        return articles.map((article, index) => (
            <Article key={index} article={article} />
        ));
    }
    else return [];
}

const Article = ({article}) => {
    return ( 
        <article key={article.id}>
            <a href={article.link}>{article.title}</a>
            <p>{article.description}</p>
        </article>
    );
};

const Articles = React.createClass({
    render() {
        const articles = renderArticles(this.props.articles);

        return (
            <section>
                { articles }
            </section>
        );
    }
});

module.exports = Articles;
  • 1
    Это выглядит как самый «реактивный» способ сделать это. Передать значения в качестве реквизита другому подкомпоненту. Спасибо!
  • 0
    Это здорово! Идеально подходит для случаев, когда ваш рендер () тяжелый HTML.
Показать ещё 4 комментария
18

Я использую Object.keys(chars).map(...) для цикла в рендеринге

// chars = {a:true, b:false, ..., z:false}

render() {
    return (
       <div>
        {chars && Object.keys(chars).map(function(char, idx) {
            return <span key={idx}>{char}</span>;
        }.bind(this))}
        "Some text value"
       </div>
    );
}
  • 0
    Ваш ответ сработал для меня, но только после того, как я добавил chars && ... и .bind(this) в конце своей функции. Мне любопытно, почему просто Object... (и так далее, и тому подобное) не работал. Я продолжал становиться неопределенным.
  • 0
    Это не отвечает на вопрос, в частности, говорится, что для анализа не требуется массив объектов, а в объяснении явно говорится, что я хочу преобразовать цикл for в карту для рендеринга в компоненте React. Вы заменили массив объектом, который не помогает ответить на вопрос, или добавили какое-либо дополнительное значение.
1

Вот альтернативный синтаксис

Я очень часто использую этот фрагмент со списками, jsx и жирными стрелками:

return (
  {
    obj &&
      <ul className={styles.obj}>
        { Object.keys(obj).map((k, index) => <li key={index}>{ `${k}: ${obj[k]}` }</li>) }
      </ul>
  }
)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню