Создание динамического списка ссылок в response-router

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

Я просматриваю массив строк с именем nameArr. Я хотел бы создать список интерактивных ссылок строк с помощью response-router, чтобы каждая ссылка перемещалась по маршруту, определенному в route.js.

Массив nameArr заполняется из ответа, созданного сервером.

Следующий код фокусируется на создании списка и применении его к JSX.

var React = require('react');
var Router = require('react-router');
var createReactClass = require('create-react-class');
var Link = Router.Link;  
var request = require('superagent'); //Superagent is an AJAX API used in Node.

var classComp = createReactClass({

request.post('/getdata')
        .end(function (err, res) {
            if (err || !res.ok) {
                console.info('Oh no! err');
            } else {
                var response = JSON.parse(res.text);
                var i;
                var pathArr = [];
                var nameArr = [];

                for (i = 0; i < response.length; i++) {
                    pathArr[i] = response[i].videourl;
                    nameArr[i] = response[i].name;
                }
var displayItem = "<div className=\"container\">";

                for (var m in nameArr) {
                  displayItem += "<div class='text-center'><Link to='play'><h3>" + nameArr[m].toString() + "</h3></Link></div>";
                }

                displayItem += "</div>";
                document.getElementById("vdlist").innerHTML = displayItem;
}

render: function () {
    return (
        <div className = "container center-block vlsection1">
            {this.display()}
            <h1 className = "text-center">Videos</h1>
            <div id = "vdlist">

            </div>
        </div>
    );
}
});

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

Большое спасибо!

В качестве отступления я бы рекомендовал использовать одинарные кавычки в вашем JS и двойные кавычки для вашего HTML - таким образом вам не нужно будет экранировать свой код: '<div className = "container">'.

Andy 19.03.2018 12:32

ты сделал import {Link} from "react-router-dom"? вы получаете значение `nameArr [m] .toString ()`, не могли бы вы обновить свой вопрос дополнительной информацией?

Abslen Char 19.03.2018 12:34

Вы пытаетесь добиться побочного эффекта в своей функции рендеринга, побочным эффектом которого является «Найдите #id vdlist и взломайте его innerHTML». На мой взгляд, это было бы лучше сделать в componentDidMount и / или componentDidUpdate. Я удивлен, что при запуске вы не получаете ошибку консоли JS. Я бы подумал, что элемент #vdlist не существует при запуске .display(). React имеет встроенную поддержку генерации HTML, почему бы вам не использовать ее? В этом случае вы можете вернуть JSX из .display(), и React выполнит обновление вашего HTML при обновлении nameArr.

Rajit 19.03.2018 12:38

Привет, Раджит, спасибо за информацию. Однако я хотел бы сказать, что ошибки консоли не было, а также список заполняется. Это означает, что #vdlist идентифицирован. Проблема в том, что элементы списка представляют собой текст, а не ссылки, как я хочу. В любом случае, я постараюсь, как вы предлагаете, и обновлю.

Kuzan 19.03.2018 12:49

Привет, Абдеслем, я обновил вопрос. Пожалуйста, сообщите, если требуется дополнительная ясность.

Kuzan 19.03.2018 12:50

Привет, Энди, Спасибо за рекомендацию.

Kuzan 19.03.2018 12:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
6
3 553
2

Ответы 2

Более идиоматический способ сделать это:

render: function () {
  return (
    <div className = "container center-block vlsection1">
      <h1 className = "text-center">Videos</h1>
      <div id = "vdlist">
        {nameArr.map(name => (
          <div key = {name} className = "container">
            <div class = "text-center"><Link to = "play"><h3>{name.toString()}</h3></Link></div>
          </div>
        ))}
      </div>
    </div>
  );
}

К вашему сведению, вы не можете использовать элементы только JSX (например, <Link/>) в .innerHTML.

ИЗМЕНИТЬ [Пояснение]: React создан, чтобы упростить управление динамическими веб-страницами, и по существу устраняет необходимость использовать такие вещи, как .innerHTML. Если вы используете React и пытаетесь использовать .innerHTML, скорее всего, вы идете в неправильном направлении.

Вы можете быть уверены, что любой элемент с заглавной буквы не является исходным элементом HTML, а является компонентом React. Если это так, то подходящее место для его использования - в блоке JSX (или, возможно, непосредственно в качестве компонента React, если хотите). Итак, <Link/>, <Router/> и любой другой тег, начинающийся с заглавной буквы.

Я добавил блок JavaScript в ваш .render JSX, который сопоставляется с массивом nameArr и генерирует код, который вы пытались сгенерировать из вашего метода .display. Как видите, вы можете вставить произвольный JavaScript в JSX, поместив его между фигурными скобками {}.

ИЗМЕНИТЬ [чтобы ответить на обновленный вопрос]: Ваша переменная nameArr доступна только в функции .end() для запроса, который вы делаете, поэтому, конечно, у вас нет доступа к ней в функции render. React предоставляет функцию именно для этого случая! Состояние реакции! Вы можете узнать больше о Состояние и жизненный цикл.

В этом случае все, что вам нужно сделать, это инициализировать какое-то состояние для вашего класса, а затем обновить его, когда вы получите новые данные. То, как вы инициализируете состояние с использованием стиля до ES6, который вы используете, - это добавление ключа getInitialState к вашему аргументу createReactClass:

getInitialState: function() {
  return { nameArr: [] };
},

В этом случае я инициализировал nameArr как пустой массив. Затем в вашей функции render вы можете обратиться к this.state.nameArr:

render: function () {
  return (
    <div className = "container center-block vlsection1">
      <h1 className = "text-center">Videos</h1>
      <div id = "vdlist">
        {this.state.nameArr.map(name => (
          <div key = {name} className = "container">
            <div class = "text-center"><Link to = "play"><h3>{name.toString()}</h3></Link></div>
          </div>
        ))}
      </div>
    </div>
  );
}

Как только вы это сделаете, если мы его нигде не обновим, он всегда будет пустым. Чтобы обновить его, мы вызываем this.setState({ ... }). Вот как это будет работать с вашим вызовом запроса:

request.post('/getdata')
  .end(function (err, res) {
    var response;
    var i;
    var nameArr = [];

    if (err || !res.ok) {
      console.info('Oh no! err');
      // NOTE: You should probably set an error in state here:
      // this.setState({ error: '...' });
    } else {
      var response = JSON.parse(res.text);

      // NOTE: .map is an easier way to extract the name here
      nameArr = response.map(function (p) { return p.name });

      // This is where you update your React state.
      this.setState({ nameArr: nameArr });
    }
  });

Как только вы это сделаете, ваш класс React должен обновиться быстро и эффективно. В этом сила React, и, надеюсь, вы видите, что это намного проще, чем пытаться создавать HTML заново. Вместо этого вы можете просто положиться на один метод render.

Такое же решение, как и у меня, извините. Обратите внимание, что вы забыли изменить class = "text-center" на className = "text-center" в методе карты. Это сделано, чтобы предотвратить конфликт ключевых слов класса с классами javascript.

Larce 19.03.2018 12:59

Спасибо, пропустил!

Rajit 19.03.2018 16:58

Привет, Раджит, Спасибо за быстрый ответ и информацию. Я обновил вопрос дальше. nameArr не является состоянием компонента класса. Я использовал его, чтобы получить данные из ответа, обновленного в вопросе. Также как новичок я использую Javascript без ES6 для реагирования. Пожалуйста, предложите.

Kuzan 20.03.2018 06:21

MVG_INFINITY_CODER, вы довольно существенно изменили свой вопрос. Первоначально ваш вопрос касался попытки использовать .innerHTML с элементами JSX, а теперь он сосредоточен вокруг того факта, что nameArr доступен только в асинхронном фрагменте кода. Я бы посоветовал вам отправить новый вопрос, а не обновлять его таким образом. Однако на этот раз я просто дополню свой ответ.

Rajit 26.04.2018 10:16

Как уже упоминалось в комментарии Раджита, вы пытаетесь получить доступ к элементу dom в функции рендеринга. Это никогда не бывает хорошей идеей, и никогда не следует ее делать.

В React также неправильный способ прямого доступа к dom, поскольку вы потеряете некоторые мощные инструменты реагирования, такие как виртуальный dom.

Лучше использовать JSX. И под JSX я имею в виду настоящий JSX. Есть разница между строкой, которая «выглядит» как JSX, и фактическим JSX. Вы пытаетесь создать строку с JSX внутри. Затем вы добавляете эту строку в дом - используя свойство innerHTML. Однако ваш JSX на самом деле не будет обрабатываться как JSX. Он будет обрабатывать его как HTML - а в HTML нет элемента <Link />. Вот почему вы не видите предметы.

Вместо этого сделайте это так:

import React, { Component } from 'react';
import { Link } from 'react-router-dom'; // You need to use react-router-dom here

class VideoList extends Component {
  constructor(props) {
    super(props);
    this.nameArr = ['name1', 'name2'];
  }

  getVideos() {
    // This creates a JSX element for every name in the list.
    return this.nameArr.map(name => <div className = "text-center"><Link to = "play"><h3>{name}</h3></Link></div>);
  }

  render() {
    return (
      <div className = "container center-block vlsection1">
        <h1 className = "text-center">Videos</h1>
        {this.getVideos()}
    </div>
    );
  }
}

Привет, Ларс, Спасибо за быстрый ответ и информацию. Поскольку я обновил вопрос, я хотел бы сказать, что nameArr не является состоянием компонента. Также я изучаю React, используя Javascript без ES6. Пожалуйста, предложите.

Kuzan 20.03.2018 06:23

Другие вопросы по теме