【问题标题】:Why is one of my child components able to get handleClick() but the others are not?为什么我的子组件之一能够获取 handleClick() 而其他子组件不能?
【发布时间】:2020-03-29 07:27:45
【问题描述】:

问题

我正在根据仪表板(父)组件中的状态交换组件并将道具传递给所有组件。当我使用批发商登录时,应用程序运行没有问题,但是当我使用零售商帐户登录时,应用程序返回

TypeError: this.props.handleClick 不是函数

当我点击按钮-handleClick() -> 通过改变状态的 handleClick 切换组件

我的组件几乎相同,我不知道这是从哪里来的。

提前感谢您! :)

文件

Dashboard.js

import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import { Retailers } from './_components/Retailers'
import { Locations } from './_components/Locations'
import { Products } from './_components/Products'

class Dashboard extends Component {
  constructor(props) {
    super(props)

    this.state = {
      chosenRetailerId: null,
      chosenLocationId: null,
      mountComponent: ''
    }

    this.handleClick = this.handleClick.bind(this)
  }

  componentDidMount() {
    switch (this.props.user.type) {
      case 'wholesaler':
        this.setState({ mountComponent: "retailers" })
        break;
      case 'retailer':
        this.setState({ mountComponent: "locations" })
        break;
      case 'location':
        this.setState({ mountComponent: "products" })
        break;
      default:
        break;
    }
  }

  handleClick(id, shouldMountComponent) { 
    switch (shouldMountComponent) {
      case 'locations':
        this.setState({
          mountComponent: shouldMountComponent,
          chosenRetailerId: id
        })
        break;
      case 'products':
        this.setState({
          mountComponent: shouldMountComponent,
          chosenLocationId: id
        })
        break;
      default:
        break;
    }
  }

  render() {
    const { user } = this.props
    const { chosenLocationId, chosenRetailerId, mountComponent } = this.state

    return (
      <div className="dashboard">
        {user.type === 'wholesaler' &&
          <div className="wholesaler">
            <h1>Wholesaler</h1>
            <h3>{user._id}</h3>
            {this.state.mountComponent === 'retailers' &&
            <Retailers mountComponent={mountComponent} handleClick={this.handleClick} />
            }
            {this.state.mountComponent === 'locations' &&
            <Locations retailerId={chosenRetailerId} locationId={chosenLocationId} mountComponent={mountComponent} handleClick={this.handleClick} />
            }            
            {this.state.mountedComponent === 'products' &&
            <Products locationId={chosenLocationId} mountComponent={mountComponent}/>
            }
          </div>
        }
        {user.type === 'retailer' &&
          <div className="retailers">
            <h1>Retailer {user._id}</h1>
            <Locations locationId={chosenLocationId}/>
          </div>
        }
        {user.type === 'location' &&
          <div className="locations">
            <h1>Location {user._id}</h1>
            <Products />
          </div>
        }
        <p>You're logged in with React & JWT!!</p>
        <p>
          <Link to="/login">Logout</Link>
        </p>
      </div>
    )
  }
}

function mapStateToProps(state) {
  const { authentication } = state
  const { user } = authentication

  return {
      user
  }
}

const connectedDashboard = connect(mapStateToProps)(Dashboard)
export { connectedDashboard as Dashboard }

Retailers.js

import React, { Component } from 'react'
import { connect } from 'react-redux'

class Retailers extends Component {
    state = {
        retailers: []
    }

    componentDidMount() {
        const { user } = this.props

        const requestOptions = {
            method: 'GET',
            headers: { 'Authorization': 'Bearer ' + user.token }
        }

        fetch(`http://localhost:4000/retailers/by-wholesaler/${user._id}`, requestOptions)
            .then(result => result.json())
            .then(result => {
                this.setState({
                    retailers: result
                })
            })
    }

    render() {
        const { retailers } = this.state

        return (
            <div className="retailers">
                {retailers.map((retailer, index) =>
                <button key={index} onClick={() => this.props.handleClick(retailer._id, 'locations')}>{retailer.name}</button>
                )}
            </div>
        )
    }
}

function mapStateToProps(state) {
    const { authentication } = state
    const { user } = authentication

    return { user }
}

const connectedRetailers = connect(mapStateToProps)(Retailers)
export { connectedRetailers as Retailers }

Locations.js

import React, { Component } from 'react'
import { connect } from 'react-redux'

class Locations extends Component {
    state = {
        locations: []
    }

    componentDidMount() {
        const { user } = this.props

        const requestOptions = {
            method: 'GET',
            headers: { 'Authorization': 'Bearer ' + user.token }
        }

        const retailerId = (user.type === 'retailer') ? user._id : this.props.retailerId
        console.log(retailerId)

        fetch(`http://localhost:4000/locations/by-retailer/${retailerId}`, requestOptions)
            .then(result => result.json())
            .then(result => {
                this.setState({
                    locations: result
                })
            })
    }

    render() {
        const { locations } = this.state

        return (
            <div className="locations">
                {locations.map((location, index) =>
                <button key={index} onClick={() => this.props.handleClick(location._id, 'products')}>{location.name}</button>
                )}
            </div>
        )
    }
}

function mapStateToProps(state) {
    const { authentication } = state
    const { user } = authentication

    return { user }
}

const connectedLocations = connect(mapStateToProps)(Locations)
export { connectedLocations as Locations }

【问题讨论】:

    标签: javascript node.js reactjs redux


    【解决方案1】:

    您必须将handleCLick 传递给location 作为道具。您在批发商的情况下这样做(将其传递给零售商组件),但在使用 Locations 组件时不会这样做

    【讨论】:

    • 我没有注意到我正在使用开关盒...非常感谢你让我大开眼界 :)
    【解决方案2】:

    您没有将handleClick 作为道具传递:)

    <Retailers handleClick={this.handleClick} />
    <Locations handleClick={this.handleClick} />
    

    所以 prop 是未定义的,您不能将其作为函数调用。

    【讨论】:

      【解决方案3】:

      检查 Locations.js 中的 locations.map 函数。 您正在将所谓的 thisArg 传递给 map 函数,因此它不再使用正确的上下文。

      这应该可行:

      <div className="locations">
          {locations.map((location, index) =>
              <button key={index} onClick={() =>
                  this.props.handleClick(location._id, 'products')}>
                  {location.name}
              </button>
           )}
      </div>
      

      另外,考虑使用 uuid 包作为迭代密钥。现在您正在使用一个索引,如果您在另一个迭代中也这样做,那么它不会是唯一的(目前还不是这样)。

      【讨论】:

      • 仍然无法正常工作 :( 谢谢你的帮助 :)
      • DSCH 是对的,你有一个位置组件,事件没有通过。
      猜你喜欢
      • 2019-02-24
      • 2019-03-18
      • 2016-05-15
      • 2021-01-10
      • 2020-01-10
      • 2017-12-25
      • 2020-01-09
      • 2021-12-29
      • 2011-04-23
      相关资源
      最近更新 更多