Почему один из моих дочерних компонентов может получить handleClick (), а другие нет? - PullRequest
0 голосов
/ 29 марта 2020

ПРОБЛЕМА

Я меняю компоненты на основе состояния в компоненте Dashboard (родительский) и передаю реквизиты всем им. Когда я вхожу с помощью оптовика, приложение работает без проблем, но когда я вхожу с учетной записью продавца, приложение возвращает

TypeError: this.props.handleClick не является функцией

когда я нажимаю на button-handleClick () -> переключаю компоненты через handleClick, который меняет состояние

Мои компоненты почти идентичны, и я понятия не имею, откуда это.

Спасибо Вы заранее! :)

Файлы :

Панель инструментов. 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 }

Розничные продавцы. 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 }

Местоположения. 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 }

Ответы [ 3 ]

2 голосов
/ 29 марта 2020

Вы не передали handleClick как реквизит:)

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

Итак, реквизит не определен, и вы не можете вызвать его как функцию.

2 голосов
/ 29 марта 2020

Вы должны передать handleCLick в location в качестве реквизита. Вы делаете это в случае с оптовиком (передавая его компоненту розничной торговли), но не при использовании компонента Locations

0 голосов
/ 29 марта 2020

Проверьте функцию locations.map в своих местах. js. Вы передаете так называемую thisArg функции карты, поэтому она больше не использует правильный контекст.

Это должно работать:

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

Также подумайте об использовании * Пакет 1008 * для ваших ключей итерации. Теперь вы используете индекс, и он не будет уникальным, если вы сделаете это и на другой итерации (еще не так).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...