我正在学习react-router,我在以下问题中需要帮助:
我正在遍历名为nameArr的字符串数组。我想使用react-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.log('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>
);
}
});
当我运行应用程序时,会生成List但链接未显示。单击链接时没有动作。请建议我如何以更好的方式解决这个问题。
非常感谢!
答案 0 :(得分:0)
更为惯用的方式:
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>
);
}
仅供参考,您不能在<Link/>
中使用仅限JSX的元素(例如.innerHTML
)。
EDIT [说明]:
React旨在使管理动态网页变得更加容易,并且基本上取代了使用.innerHTML
之类的东西的需要。如果你正在使用React并发现自己试图使用.innerHTML
,那么你很可能会走错方向。
您可以确定的任何大写元素都不是原始HTML元素,而是React组件。如果是这种情况,则使用它的适当位置在JSX块内(或者如果您愿意,可以直接作为React组件)。所以<Link/>
,<Router/>
以及以可填写的字母开头的任何其他标记。
我所做的是为.render
JSX添加了一块JavaScript,映射到nameArr
数组,并生成您尝试从.display
方法生成的代码。如您所见,您可以将任意JavaScript插入到JSX中,方法是将它放在{}
括号之间。
编辑[回答更新的问题]:
您的nameArr
变量仅适用于您正在进行的请求的.end()
函数,因此您无法在render
函数中访问该变量。 React为这种情况提供了一个功能!反应状态!您可以阅读有关State and Lifecycle。
在这种情况下,您需要做的就是为您的类初始化某个状态,然后在收到新数据时更新它。使用您正在使用的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.log('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
方法。
答案 1 :(得分:0)
正如Rajit的评论中已经提到的,您尝试在render函数中访问dom元素。这绝不是一个好主意,不应该做。
React直接访问dom也不是正确的方法,因为你会失去一些强大的反应工具,比如虚拟dom。
更好的方法是使用JSX。通过JSX,我的意思是真正的JSX。字符串&#34;看起来&#34;之间存在差异。像JSX和实际的JSX。你尝试做的是在里面用JSX创建一个字符串。然后使用innerHTML属性将此字符串添加到dom中。但是,你的JSX真的不能作为JSX来处理。它只会像HTML一样处理它 - 而且没有&lt; Link /&gt; HTML中的元素。这就是为什么你看不到这些物品的原因。
而是这样做:
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>
);
}
}