简单的道具示例,但找不到道具

时间:2018-06-20 20:58:59

标签: javascript reactjs

在反应书的下一章中,我决定尝试构建一些代码来测试道具在反应中的工作方式。我有以下应用程序:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
// Import Component
import PropExample from './simple-props'
const ctitle = "Sample app"
class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">{ctitle}</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
        <div className='custom-components-list'>
          <PropExample />
        </div>
      </div>
    );
  }
}

export default App;

组件PropExample正在使用容器/容器设计模式。因此,它具有PropXCard两个组成部分。 PropX父级从api获取数据并更新其状态。卡通过道具接收该数据并进行渲染。

这两个组件的代码如下:

/*
  Simple component to read from api and present data
  Propx to get data from api and function as container to Card component
  Card component to present data to UI and leverage material ui
*/
import React, {Component} from 'react'
import Card from './card'
class PropX extends Component{
  constructor(props){
    super(props)
    state:{
      data:[{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      }]
    }
  }
  //Lifecycle hook that will grab data right before component is mounted to the dom
  componentWillMount(){
    let url = 'https://jsonplaceholder.typicode.com/users'
    fetch(url)
    .then((res)=>{ // Note that this a response object, need to look more into promises, fetch api and response object in javascript
      //console.log(`The response is ${res}`)
      return res.json()
    })
    .then(data => {
      //console.log(`The data is ${data}`)
      this.setState({data})
    })
    .catch(err=>{
      console.log(`The error is ${err}`)
    })
  }

  render(){
    return(
      <div>
        <Card data={this.state}/>
      </div>
    )
  }
}
export default PropX

和卡片:

/*
  Card component
  Reads data fetched from  parent PropX
  Produces Cards with sylized data
*/
import React, {Component} from 'react'
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Avatar from '@material-ui/core/Avatar';
import ImageIcon from '@material-ui/icons/Image';
import WorkIcon from '@material-ui/icons/Work';

class Card extends Component{
  constructor(props){
    super(props)
  }
  render(){
    return(
    <ul>
      {this.props.data.map(i => {
        return (
          <li key={i}> {i.name}</li>
        )
      })}
    </ul>
    )
  }
}
export default Card

运行此命令时,出现以下错误:

TypeError: Cannot read property 'map' of null
Card.render
card.js:21
  18 | render(){
  19 |   return(
  20 |   <ul>
> 21 |     {this.props.data.map(i => {
  22 |       return (
  23 |         <li key={i}> {i.name}</li>
  24 |       )

删除this不能解决问题。谁能告诉我这是怎么了?

我还试图使用材料ui(随--save一起安装),但是由于我不知道为什么我没有数据,所以到目前为止我还没有使用任何组件。

1 个答案:

答案 0 :(得分:1)

您的问题出在PropX的构造函数中

  constructor(props){
    super(props)
    state:{ // okay... so this is referenced where?
      data:[{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      }]
    }
  }

您需要在构造函数中将state分配为this上的属性,以便稍后在传递它时对其进行实际分配

  constructor(props){
    super(props)
    this.state = { // now it's this.state
      data:[{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      },{
        name: 'Grrot',
        city: "grav",
        zip: 32453
      }]
    }
  }

当然,现在当您在卡中致电.map()时,您会得到一个不同的错误。您可能想做的是改为将this.state.data传递到卡上

render(){
  return(
    <div>
      <Card data={this.state.data}/>
    </div>
  )
}