skip to Main Content

I am attempting to pass props up to a parent component from a dynamically rendered function in a react component.

I am defining the function the same way as the other functions are defined in react, but react is giving me the error

Cannot read properties of undefined (reading 'setCustomer')

I am confused by this error, because I would think the functions are being defined together at run time, so the render function should be able to access the functionality of the other component from this. I initially thought I was binding the function to this incorrectly, but I kept encountering the issue.

I have reviewed a couple of other posts that are in StackOverflow, and while I have observed many similarities in their questions, there seems to be one difference between their questions and mine that is driving react to behave this way despite me attempting to use the solutions provided by others in this community, and that is the fact that I am attempting to access a function within a dynamically rendered function.

I suspect that I am contradicting best practice, but I don’t know which one it is. I am open to coding this an entirely different way – but I am attempting to write a rude version of an application for an idea I have, so I am not looking to make this perfect. I just want to write this application idea I have right now and look at it to see if the idea is any good. Please review the below:

export default class Customers extends React.Component{
   constructor(props){
     //won't burden you with the constructor stuff
   }
 // this pulls a list of customers.
   getListOfCustomers(){
           fetch(variables.API_URL + 'CustomerAPI', API_CALL_HEADER_GET_REQUEST)
            .then(response => response.json())
            .then(returnedResponse => {
                this.setState({customerList: returnedResponse})
            }).catch(error => {
                if (error) console.log(error)
            })
   }

  //this is the function that is incurring the error
       setCustomer = (customer) => {
        console.log('this does not fire at all.')
        this.props.setActiveCustomer(customer.CustomerName)
        console.log(customer)
    }

  //This is the dynamically rendered function that contains a call to 'setCustomer' above
 // that causing the error.

    renderCustomerRow(customer){
        let customerCard = customer
        return(
            <div className='Component-Element-Container' onClick= 
              {this.setCustomer(customerCard)}>
            <a href={`/Customer/${customer.CustomerName.replace(/s/g, '')}`}>
               <h3>{customer.CustomerName}</h3>
            </a>
                <p>{customer.CustomerStreet1}</p>
            </div>
        )
    }

 the render function for the class is below, incase it is helpful.

    render(){
        const CustomerList = 
                     this.state.customerList.slice(this.state.firstPage,this.state.lastPage)
        return(
            <div className='Customers'>
                <HeaderComponent component={this.state.component}/>
                 <div className='Component-Body'>
                    {CustomerList.length > 0 ? CustomerList.map(this.renderCustomerRow) : <div>No number</div>}
                 <div className='component-element-container'>
                        <div className='center'>
                                <button className='green forward-button' id='forward-button'onClick={this.handleClick.bind(this)}>Click</button>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}
 

2

Answers


  1. I’m pretty sure you cannot define anonymous function inside class.

    Try this:

    setCustomer(customer) {
      console.log("this does not fire at all.");
      this.props.setActiveCustomer(customer.CustomerName);
      console.log(customer);
    };
    
    export default class Customers extends React.Component {
      constructor(props) {
        //won't burden you with the constructor stuff
      }
      // this pulls a list of customers.
      getListOfCustomers() {
        fetch(variables.API_URL + "CustomerAPI", API_CALL_HEADER_GET_REQUEST)
          .then((response) => response.json())
          .then((returnedResponse) => {
            this.setState({ customerList: returnedResponse });
          })
          .catch((error) => {
            if (error) console.log(error);
          });
      }
    
      //this is the function that is incurring the error
      setCustomer(customer) {
        console.log("this does not fire at all.");
        this.props.setActiveCustomer(customer.CustomerName);
        console.log(customer);
      };
    
      renderCustomerRow(customer) {
        let customerCard = customer;
        return (
          <div
            className="Component-Element-Container"
            onClick={this.setCustomer(customerCard)}
          >
            <a href={`/Customer/${customer.CustomerName.replace(/s/g, "")}`}>
              <h3>{customer.CustomerName}</h3>
            </a>
            <p>{customer.CustomerStreet1}</p>
          </div>
        );
      }
    
      render() {
        const CustomerList = this.state.customerList.slice(
          this.state.firstPage,
          this.state.lastPage
        );
        return (
          <div className="Customers">
            <HeaderComponent component={this.state.component} />
            <div className="Component-Body">
              {CustomerList.length > 0 ? (
                CustomerList.map(this.renderCustomerRow)
              ) : (
                <div>No number</div>
              )}
              <div className="component-element-container">
                <div className="center">
                  <button
                    className="green forward-button"
                    id="forward-button"
                    onClick={this.handleClick.bind(this)}
                  >
                    Click
                  </button>
                </div>
              </div>
            </div>
          </div>
        );
      }
    }

    Another question, why are you still using class Components?

    Login or Signup to reply.
  2. The problem is likely coming from the CustomerList.map(this.renderCustomerRow) call in render(). If renderCustomerRow() is not bound then this will be undefined when it runs, hence the error "Cannot read properties of undefined (reading ‘setCustomer’)".

    In general using the constructor to bind all methods that might be referenced from outside the scope of the class (including in e.g. Array.map) will avoid these kinds of problems. (Binding when passing the function as an argument is also common, but easy to forget.)

    e.g.

    constructor(props) {
      this.setCustomer = this.setCustomer.bind(this);
      this.renderCustomerRow = this.renderCustomerRow.bind(this);
    }
    

    Hope that helps!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search