Я изучаю реактивный маршрутизатор, и мне нужна помощь в следующей проблеме:
Я просматриваю массив строк с именем 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>
);
}
});
Когда я запускаю приложение, список создается, но ссылки не отображаются. Когда я нажимаю на ссылки, никаких действий не происходит. Пожалуйста, подскажите, как мне лучше подойти к этой проблеме.
Большое спасибо!
ты сделал import {Link} from "react-router-dom"? вы получаете значение `nameArr [m] .toString ()`, не могли бы вы обновить свой вопрос дополнительной информацией?
Вы пытаетесь добиться побочного эффекта в своей функции рендеринга, побочным эффектом которого является «Найдите #id vdlist и взломайте его innerHTML». На мой взгляд, это было бы лучше сделать в componentDidMount и / или componentDidUpdate. Я удивлен, что при запуске вы не получаете ошибку консоли JS. Я бы подумал, что элемент #vdlist не существует при запуске .display(). React имеет встроенную поддержку генерации HTML, почему бы вам не использовать ее? В этом случае вы можете вернуть JSX из .display(), и React выполнит обновление вашего HTML при обновлении nameArr.
Привет, Раджит, спасибо за информацию. Однако я хотел бы сказать, что ошибки консоли не было, а также список заполняется. Это означает, что #vdlist идентифицирован. Проблема в том, что элементы списка представляют собой текст, а не ссылки, как я хочу. В любом случае, я постараюсь, как вы предлагаете, и обновлю.
Привет, Абдеслем, я обновил вопрос. Пожалуйста, сообщите, если требуется дополнительная ясность.
Привет, Энди, Спасибо за рекомендацию.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Более идиоматический способ сделать это:
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.
Спасибо, пропустил!
Привет, Раджит, Спасибо за быстрый ответ и информацию. Я обновил вопрос дальше. nameArr не является состоянием компонента класса. Я использовал его, чтобы получить данные из ответа, обновленного в вопросе. Также как новичок я использую Javascript без ES6 для реагирования. Пожалуйста, предложите.
MVG_INFINITY_CODER, вы довольно существенно изменили свой вопрос. Первоначально ваш вопрос касался попытки использовать .innerHTML с элементами JSX, а теперь он сосредоточен вокруг того факта, что nameArr доступен только в асинхронном фрагменте кода. Я бы посоветовал вам отправить новый вопрос, а не обновлять его таким образом. Однако на этот раз я просто дополню свой ответ.
Как уже упоминалось в комментарии Раджита, вы пытаетесь получить доступ к элементу 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. Пожалуйста, предложите.
В качестве отступления я бы рекомендовал использовать одинарные кавычки в вашем JS и двойные кавычки для вашего HTML - таким образом вам не нужно будет экранировать свой код:
'<div className = "container">'.