【问题标题】:JSX won't render properlyJSX 无法正确渲染
【发布时间】:2020-08-27 12:44:23
【问题描述】:

我的 JSX 不会正确显示在我的 React 网页上,而是得到以下输出:

<div class='card'>NaNSasha<img src= NaN />Boddy Cane</div>.

组件:

import React,  {Component} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';

class App extends Component{

  state = {

    string : '',
  }

  componentDidMount(){

     let posts = [

        {
          title: 'somebody toucha my spaghet',
          author: 'Karen',
          image:'https://media-cdn.tripadvisor.com/media/photo-s/11/69/c7/f9/spagetti.jpg',
          location: 'Jimmy John',
          description: 'This spagetti is amazing'
        },
        {
          title: `I love food`,
          author: 'Sasha',
          image:'https://hoodline.imgix.net/uploads/story/image/610603/donuts2.jpg?auto=format',
          location: 'Boddy Cane',
          description: 'cjndwsijnjcinjw'
        }
    
  ];

      for(let i =0; i < posts.length; i ++){

        const header = `<div class='card'>${+posts[i].title}`;
        const body = posts[i].author;
        const image = `<img src= ${+posts[i].image} />`;
        const description = `${posts[i].location}</div>`;
  
        const concatThis = header + body + image + description
        this.setState({
  
          string: concatThis
        });
      };
    };
    
  render(){

    return(

      <div className='container'>
      {this.state.string}
      </div>
      
    
    )
  }
}

export default App;

P.S 我是学生

【问题讨论】:

  • 请阅读How to Askstackoverflow.com/help/formatting。来自How to Ask:不要试图把你的整个问题塞进标题,也不要把整个问题都写成你的代码。添加一些描述问题、您所期望的内容等的文本。
  • 为什么会有 + &lt;img src= ${+posts[i].image} /&gt; 和标题?
  • 我知道这不是一个答案,但是您编写代码的方式既难以阅读又难以编写。使用列表渲染 -> reactjs.org/docs/lists-and-keys.html,然后问一个问题,为什么名称弹出为NaNSasha 而不是。 :)

标签: javascript reactjs concatenation jsx


【解决方案1】:

这就是你要找的。表达式+{} 被评估为NaN。但请使用列表渲染。

        const image = `<img src= ${+posts[i].image} />`;
                                   ^ here

【讨论】:

    【解决方案2】:

    您似乎正在尝试构建一个字符串,然后将其存储在一个状态中并在更新后呈现该字符串。不幸的是,这不是你应该使用 React 的方式。

    state 只能是原始数据,例如带有对象的 posts 数组。它保存组件的内容和数据,不应该关心除此之外的其他任务。显然,您可以将任何类型的数据置于状态中,例如字符串。

    state = {
      title: 'My food blog',
      description: 'Awesome stuff about food',
      posts: [
        {
          title: 'somebody toucha my spaghet',
          author: 'Karen',
          image:'https://media-cdn.tripadvisor.com/media/photo-s/11/69/c7/f9/spagetti.jpg',
          location: 'Jimmy John',
          description: 'This spagetti is amazing'
        },
        {
          title: `I love food`,
          author: 'Sasha',
          image:'https://hoodline.imgix.net/uploads/story/image/610603/donuts2.jpg?auto=format',
          location: 'Boddy Cane',
          description: 'cjndwsijnjcinjw'
        }
      ]
    }
    

    只要组件已放置在页面上并且现在正在工作,就会触发componentDidMount 方法。在那里,您可以执行诸如更改数据或从服务器下载数据之类的操作。你会在那里这样做是有道理的,因为你首先会显示你的组件,也许会显示它正在加载,然后从服务器获取数据。完成后,用新数据更新组件的状态,render 方法将用新数据调用。例如(用于说明目的):

    componentDidMount() {
      fetch('urlofdatathatyouwant') // Uses AJAX to get data from anywhere you want with the Fetch API.
        .then(response => response.json()) // Tells it to read turn the response from JSON into an usable JavaScript values.
        .then(data => {
          this.setState({
            posts: data // Use the new data to replace the posts. This will trigger a new render.
          });
        });
    }
    

    render 方法应该主要关注您所在州的数据表示。在这种情况下,它应该遍历 posts 状态的元素并为每个帖子创建一个 React 元素。

    render() {
      const { posts } = this.state;
      return(
        <div className='container'>
          {posts.map(({ title, author, image, location, description }) => ( 
            // Loop over each post and return a card element with the data inserted.
            <div className="card">
              <span>{title}</span>
              <span>{author}</span>
              <img src={image} alt={title}/>
              <span>{location}</span>
              <span>{description}</span>
            </div>
          ))}
        </div>
      )
    }
    

    所有放在一起看起来像下面的例子。所以 state 只保存数据,componentDidMount 是组件在页面上之后对数据进行操作的地方,render 只输出您需要使用 JSX 创建的 HTML。

    import React, { Component } from 'react';
    import 'bootstrap/dist/css/bootstrap.min.css';
    
    class App extends Component{
    
      state = {
        posts: [
          {
            title: 'somebody toucha my spaghet',
            author: 'Karen',
            image:'https://media-cdn.tripadvisor.com/media/photo-s/11/69/c7/f9/spagetti.jpg',
            location: 'Jimmy John',
            description: 'This spagetti is amazing'
          },
          {
            title: `I love food`,
            author: 'Sasha',
            image:'https://hoodline.imgix.net/uploads/story/image/610603/donuts2.jpg?auto=format',
            location: 'Boddy Cane',
            description: 'cjndwsijnjcinjw'
          }
        ]
      }
    
      componentDidMount() {
        // Do something here with the posts if you need to.
      }
        
      render() {
        const { posts } = this.state;
        return(
          <div className='container'>
            {posts.map(({ title, author, image, location, description }, index) => (
              <div key={index} className="card">
                <span>{title}</span>
                <span>{author}</span>
                <img src={image} alt={title}/>
                <span>{location}</span>
                <span>{description}</span>
              </div>
            ))}
          </div>
        )
      }
    }
    
    export default App;
    

    您甚至可以通过将卡片元素也作为组件来使它变得更好。而且由于它(还)没有任何功能,它只需要控制输出。

    const Card = ({ title, author, image, location }) => (
      <div className="card">
        <span>{title}</span>
        <span>{author}</span>
        <img src={image} alt={title}/>
        <span>{location}</span>
        <span>{description}</span>
      </div>
    )
    

    然后将卡片导入您的App 组件并在render 方法中使用。

    // App.jsx render.
    render() {
      const { posts } = this.state;
      return(
        <div className='container'>
          { /* ...post taking all the properties of each post and passes them to the card element */ }
          {posts.map((post, index) => <Card key={index} {...post} />)} 
        </div>
      )
    }
    

    【讨论】:

    • 为什么要引入 REST?这完全超出了问题的范围。
    • 我知道。这是为了说明您可以在componentDidUpdate 方法中对处理数据所做的事情。正如 OP 提到她是一名学生,我认为它会通过给出一个真实世界的例子来增加背景。我同意它超出了范围,但我会让 OP 决定是否需要删除它。