在react-router中创建链接的动态列表

时间:2018-03-19 11:29:24

标签: javascript reactjs react-router jsx react-router-v4

我正在学习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但链接未显示。单击链接时没有动作。请建议我如何以更好的方式解决这个问题。

非常感谢!

2 个答案:

答案 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>
    );
  }
}