在 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 中使用双引号 - 这样您就不需要转义代码:'&lt;div className="container"&gt;' 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 的元素(如 &lt;Link/&gt;)。

编辑[解释]: React 旨在让管理动态网页变得更容易,并且基本上取代了使用 .innerHTML 之类的东西的需要。如果你在使用 React 并发现自己在尝试使用 .innerHTML,那很可能你走错了方向。

您可以确定的任何大写元素都不是原始 HTML 元素,而是一个 React 组件。如果是这种情况,那么使用它的适当位置是在 JSX 块中(或者如果您愿意,也可以直接作为 React 组件)。所以&lt;Link/&gt;&lt;Router/&gt; 和任何其他以大写字母开头的标签。

我所做的是向您的 .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 中创建动态链接列表的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS5 视图控制器中创建链接/按钮动态列表的最佳方法

通过网状在R中创建python列表

在r中创建一个带有条件的组合列表[重复]

如何以编程方式在 Firebase 中创建动态链接?迅速

如何在R中创建列表的复杂层次结构

在 R 中创建边列表