Удвойте циклы в React, используя .map - PullRequest
0 голосов
/ 07 сентября 2018

Я пытаюсь создать двойной цикл for в React для некоторого JSON-контента, который я создал:

"students": [
        {
          "name": "person",
          "photoURL": "https://via.placeholder.com/100x100",
          "subjects":[
            "physics",
            "math",
            "english"
          ],
          "nextClass": "August 29th, 2018"
        },
        {
          "name": "human",
          "photoURL": "https://via.placeholder.com/100x100",
          "subjects":[
            "chemistry",
            "math",
            "french"
          ],
          "nextClass": "August 27th, 2018"
        }]

В моем JSX я пытаюсь перебрать объекты ученика, а затем снова перебрать все предметы, чтобы создать неупорядоченный список:

render(){

    return(
          <div id="display-students">
            {this.props.students.map((x,i) =>{
              return (
                <div className="student" key={i}>
                  <h2>{x.name}</h2>
                  <img src={x.photoURL} alt="profile"/>
                  <h3>Subjects: </h3>
                  <ul>
                      {x.subjects.map((y) => <li>{y}</li>)}
                  </ul>
                </div>  
              )
            })} 
          </div>
        )
   }

Однако эта ошибка отображается в браузере:

enter image description here

Когда я пытаюсь сделать

<ul>
    {x.subjects}
</ul>

Я вижу содержимое массива, объединенное в одну строку: enter image description here

Есть какие-нибудь указатели на то, почему это происходит? Можем ли мы даже использовать double для циклов в JSX?

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

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Я нашел решение!Я полагаю, что проблема была не столько в проблеме .map, сколько в невозможности полного понимания моих методов жизненного цикла.

x.subjects - это массив, однако он не определен при первом рендеринге, потому чтоответ от сервера еще не получен интерфейсом.

Чтобы исправить это, мне удалось сделать что-то вроде этого:

<ul>
   {x.subjects === undefined ? "loading..." : x.subjects.map((y, j) => <li key={j}>{y}</li>)}
</ul>

Это позволило для первогорендер, чтобы избежать ошибки.

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

  • отправляю действие в асинхронном вызове (используя избыточный поток) в компоненте
  • Это обновляет хранилище и передает данные в реквизит
  • Как только он это делает, компонент повторно выполняет рендеринг, отображая данные, полученные им от серверной части

Интересно, есть ли лучший способ сделать это ...

0 голосов
/ 07 сентября 2018

Я попробовал ту же логику. Он прекрасно работает в приведенном ниже компиляторе.

let students = [
        {
          "name": "person",
          "photoURL": "https://via.placeholder.com/100x100",
          "subjects":[
            "physics",
            "math",
            "english"
          ],
          "nextClass": "August 29th, 2018"
        },
        {
          "name": "human",
          "photoURL": "https://via.placeholder.com/100x100",
          "subjects":[
            "chemistry",
            "math",
            "french"
          ],
          "nextClass": "August 27th, 2018"
        }]
        
const Component = (props) => {

    return(
          <div id="display-students">
            {props.students.map((x,i) =>{
              return (
                <div className="student" key={i}>
                  <h2>{x.name}</h2>
                  <img src={x.photoURL} alt="profile"/>
                  <h3>Subjects: </h3>
                  <ul>
                      {x.subjects.map((y) => <li>{y}</li>)}
                  </ul>
                </div>  
              )
            })} 
          </div>
        )
   }
   
   ReactDOM.render(<Component students={students} />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.0/react-dom.min.js"></script>
<div id="app"/>
...