调用组件时如何传递变量

时间:2019-04-06 16:55:20

标签: reactjs

我正在构建一个微型应用程序,我想使其更清洁。 所以基本上我想拥有3个组成部分:AppListPerson

这是代码: App.js

import React, { Component } from "react";
import List from './List';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      results: [],
      search: '',
      currentPage: 1,
      todosPerPage: 3
    };
    this.handleClick = this.handleClick.bind(this);
  }

  componentWillMount() {
    this.fetchData();
  }

  fetchData = async () => {
    const response = await fetch(API);
    const json = await response.json();
    this.setState({ results: json.results });
  };

  handleClick(event) {
    this.setState({
      currentPage: Number(event.target.id)
    });
  }

  updateSearch(event) {
    this.setState({ search: event.target.value.substr(0, 20) });
  }

  render() {
    return (
      <List />
    );
  }
}

export default App;

List.js

import React, { Component } from 'react';
import Person from './Person';

class List extends Component {
    render() {
        const { results, currentPage, todosPerPage } = this.state;
    const indexOfLastTodo = currentPage * todosPerPage;
    const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
    const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo).filter(item => {
      return item.name.toLowerCase().indexOf(this.state.search) !== -1;
    });

    const renderTodos = currentTodos.map((item, index) => {
      return (
        <Person item={this.state.item} index={this.state.index}/>
      );
    });

    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(results.length / todosPerPage); i++) {
      pageNumbers.push(i);
    }

    const renderPageNumbers = pageNumbers.map(number => {
      return (
        <li className="page-link" key={number} id={number} onClick={this.handleClick} style={{cursor: "pointer"}}>{number}</li>
      );
    });

    return (
      <div className="flex-grow-1">
        <h1>Personnages de Star Wars</h1>
        <form className="mb-4">
          <div className="form-group">
            <label>Rechercher</label>
            <input 
            className="form-control" 
            type="text"
            placeholder="luke skywalker..."
            value={this.state.search}
            onChange={this.updateSearch.bind(this)}
            />
          </div>
        </form>
        <div className="row mb-5">{renderTodos}</div>
        <nav aria-label="Navigation">
          <ul id="page-number" className="pagination justify-content-center">{renderPageNumbers}</ul>
        </nav>
      </div>
    );
  }
}

export default List;

Person.js

import React, { Component } from 'react';

function Person(item, index) {
    return (
        <div className="col-lg-4 mb-4" key={index}>
      <div className="card">
        <div className="card-header">
          <h4 className="mb-0">{item.name}</h4>
        </div>
        <div className="card-body">
          <h5 className="card-title">Caractéristiques</h5>
          <ul>
            <li>Année de naissance : {item.birth_year}</li>
            <li>Taille : {item.height} cm</li>
            <li>Masse : {item.mass}</li>
            <li>Couleur des yeux : {item.eye_color}</li>
            <li>Couleur de cheveux : {item.hair_color}</li>
            <li>Couleur de peau : {item.skin_color}</li>
          </ul>
          <a href={item.url} className="btn btn-primary">Sa fiche</a>
        </div>
      </div>
    </div>
    )
}

export default Person;

我的问题是渲染时得到TypeError: Cannot read property 'results' of null

如果我在App.js中定义了每个文件,是否可以将变量放入每个文件中?

2 个答案:

答案 0 :(得分:1)

您可以在<List />组件的props中使用传递变量,方法是在调用<List />时在App.js的render函数中传递状态

render() {
  //Passing Data inside props
  <List data={this.state} />
}

在List.js中,您可以访问数据变量

const { results, currentPage, todosPerPage } = this.props.data;

答案 1 :(得分:1)

您没有以正确的方式传递数据。试试这个:

在App.js中,将所需数据传递给List组件:

render() {
    return (
      <List data={this.state}/>
    );
  }

然后在List.js中的render()方法中获取传递的数据属性,然后从那里提取数据:

render() {
     const { data } = this.props;
     const { results, search, currentPage, todosPerPage } = data;
     // ...
     // in currentTodos function dont use this.state.search but just "search", that we got above from the data variable
     // ...
     // also your renderTodos should look like this - use the item and index variables
     const renderTodos = currentTodos.map((item, index) => {
      return (
        <Person item={item} index={index}/>
      );
    });

    // ...
}

因此您的List.js应该如下所示:

import React, { Component } from 'react';
import Person from './Person';

class List extends Component {
    render() {
    // get the data
    const { data } = this.props;
    // get the properties
    const { results, search, currentPage, todosPerPage } = data;
    const indexOfLastTodo = currentPage * todosPerPage;
    const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
    const currentTodos = results.slice(indexOfFirstTodo, indexOfLastTodo).filter(item => {
      // use "search" variable
      return item.name.toLowerCase().indexOf(search) !== -1;
    });

    const renderTodos = currentTodos.map((item, index) => {
      return (
        // use item and index
        <Person item={item} index={index}/>
      );
    });

    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(results.length / todosPerPage); i++) {
      pageNumbers.push(i);
    }

    const renderPageNumbers = pageNumbers.map(number => {
      return (
        <li className="page-link" key={number} id={number} onClick={this.handleClick} style={{cursor: "pointer"}}>{number}</li>
      );
    });

    return (
      <div className="flex-grow-1">
        <h1>Personnages de Star Wars</h1>
        <form className="mb-4">
          <div className="form-group">
            <label>Rechercher</label>
            <input 
            className="form-control" 
            type="text"
            placeholder="luke skywalker..."
            value={search} // use search variable here too
            onChange={this.updateSearch.bind(this)}
            />
          </div>
        </form>
        <div className="row mb-5">{renderTodos}</div>
        <nav aria-label="Navigation">
          <ul id="page-number" className="pagination justify-content-center">{renderPageNumbers}</ul>
        </nav>
      </div>
    );
  }
}

export default List;

Person.js中的函数应具有以下声明,因为参数是从传递的道具中提取的:

function Person({item, index}) {
     // ...
}