在 react-router 中创建动态链接列表
Posted
技术标签:
【中文标题】在 react-router 中创建动态链接列表【英文标题】:Creating a dynamic list of Links in react-router 【发布时间】:2018-08-27 22:47:22 【问题描述】:我正在学习 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>
);
);
当我运行应用程序时,会生成列表,但未显示链接。当我单击链接时,不会发生任何操作。请建议我如何以更好的方式解决这个问题。
非常感谢!
【问题讨论】:
顺便说一句,我建议您在 JS 中使用单引号,在 HTML 中使用双引号 - 这样您就不需要转义代码:'<div className="container">'
。
你import Link from "react-router-dom"
了吗?你得到 `nameArr[m].toString()` 的值了吗,你能用更多信息更新你的问题吗?
你试图在你的渲染函数中实现一个副作用,副作用是“找到 vdlist 的#id 并破解它的 innerHTML”。在我看来,最好在componentDidMount
和/或componentDidUpdate
中完成。我很惊讶你在运行它时没有收到 JS 控制台错误。我认为当.display()
运行时#vdlist 元素不存在。 React 内置了对生成 HTML 的支持,你为什么不使用它呢?在这种情况下,您可以从 .display()
返回 JSX,React 将在 nameArr
更新时处理您的 HTML。
嗨拉吉特,感谢您的信息。但是我想告诉您没有控制台错误,并且正在填充列表。这意味着#vdlist 已被识别。问题是列表的元素是文本,而不是我想要的链接。无论如何,我会按照你的建议尝试更新。
嗨 Abdeslem,我已经更新了这个问题。如果需要更明确的说明,请务必通知。
【参考方案1】:
正如 Rajit 在评论中已经提到的,您尝试访问渲染函数中的 dom 元素。这绝不是一个好主意,也不应该这样做。
在 React 中直接访问 dom 也不是正确的方法,因为您将失去一些强大的 react 工具,例如虚拟 dom。
更好的方法是使用 JSX。而 JSX 是指真正的 JSX。 “看起来”像 JSX 的字符串和实际的 JSX 之间是有区别的。您尝试做的是在里面创建一个带有 JSX 的字符串。然后将此字符串添加到 dom 中 - 使用 innerHTML 属性。但是,您的 JSX 不会真正作为 JSX 处理。它只会像 HTML 一样处理它 - 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>
);
【讨论】:
嗨 Larce,感谢您的快速响应和信息。当我更新了问题时,我想告诉 nameArr 不是组件的状态。此外,我正在使用没有 ES6 的 javascript 学习 React。请提出建议。【参考方案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>
);
仅供参考,您不能在 .innerHTML
中使用仅限 JSX 的元素(如 <Link/>
)。
编辑[解释]:
React 旨在让管理动态网页变得更容易,并且基本上取代了使用 .innerHTML
之类的东西的需要。如果你在使用 React 并发现自己在尝试使用 .innerHTML
,那很可能你走错了方向。
您可以确定的任何大写元素都不是原始 HTML 元素,而是一个 React 组件。如果是这种情况,那么使用它的适当位置是在 JSX 块中(或者如果您愿意,也可以直接作为 React 组件)。所以<Link/>
、<Router/>
和任何其他以大写字母开头的标签。
我所做的是向您的 .render
JSX 添加一个 JavaScript 块,该块映射到 nameArr
数组并生成您尝试从您的 .display
方法生成的代码。如您所见,您可以将任意 JavaScript 插入到 JSX 中,方法是将其放在 大括号之间。
编辑[回答更新的问题]:
您的 nameArr
变量仅在 .end()
函数中适用于您发出的请求,因此您当然无法在 render
函数中访问它。 React 为这种情况提供了一个特性!反应状态!你可以阅读更多关于State and Lifecycle的信息。
在这种情况下,您需要做的就是为您的类初始化一些状态,然后在收到新数据时更新它。使用您正在使用的 pre-ES6 样式初始化状态的方式是在您的 createReactClass
参数中添加一个 getInitialState
键:
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
方法。
【讨论】:
与我的解决方案相同,抱歉。请注意,您忘记在 map 方法中将 class="text-center" 更改为 className="text-center"。这是为了阻止 class 关键字与 javascript 类发生冲突。 谢谢,错过了! 嗨 Rajit,感谢您的快速响应和信息。我已经进一步更新了这个问题。 nameArr 不是类组件的状态。我已经使用它从问题中更新的响应中获取数据。同样作为初学者,我使用没有 ES6 的 Javascript 进行反应。请提出建议。 MVG_INFINITY_CODER,您的问题已经相当显着地改变了。最初,您的问题是关于尝试将.innerHTML
与 JSX 元素一起使用,现在它的中心是 nameArr
仅在异步代码中可用。我建议您通常应该提交一个新问题,而不是像这样更新它。不过,这次我将只是增加我的答案。以上是关于在 react-router 中创建动态链接列表的主要内容,如果未能解决你的问题,请参考以下文章