2

I have two classes club, clubs and the main app class. In the clubs class i'm getting a list of club and I am displaying them in a <ul> list. In the club class I'm trying the get the detail of the clicked item from the clubs list. The point is I don't know how to call the detail function present in the club class in the clubs class.

Here's the details:

The Club class:

import React, { Component } from 'react';

const clubData = id => `urlto`

class Club extends Component {

constructor(props) {
super(props)
this.state = {
  requestFailed: false
}
// This binding is necessary to make `this` work in the callback
this.clubDetail = this.clubDetail.bind(this);
}

clubDetail(id) {
console.log('karim')
{/*fetch(clubData(id)
  .then(response => {
    if (!response.ok) {
      throw Error("Failed connection to the API")
    }

    return response
  })
  .then(response => response.json())
  .then(response => {
    this.setState({
      club: response
    })
  }, () => {
    this.setState({
      requestFailed: true
    })
  })*/}
}

render() {
if(!this.state.club) return <h1>No club selected !</h1>
return (
  <ul>
    <li>Name : {this.state.club.name}</li>
    <li>Email : {this.state.club.email}</li>
    <li>Website : {this.state.club.website}</li>
  </ul>
);
 }
}

 export default Club;

Clubs class:

import React, { Component } from 'react';

const clubsList = `urlto`


class Clubs extends Component {

constructor(props) {
super(props)
this.state = {
  requestFailed: false
}
}

componentDidMount() {
fetch(clubsList)
  .then(response => {
    if (!response.ok) {
      throw Error("Failed connection to the API")
    }

    return response
  })
  .then(response => response.json())
  .then(response => {
    this.setState({
      clubs: response
    })
  }, () => {
    this.setState({
      requestFailed: true
    })
  })
 }

 render() {
if(!this.state.clubs) return <h1>No results</h1>
return (
  <div>
    <ul>
    {this.state.clubs.map(function(item) {
        return <a key={item.id} onClick={Club.clubDetail(item.id)}><li key={item.id}>{item.name}</li></a>
    })}
    </ul>
  </div>
);
}
}

export default Clubs;

In the onClick prop, I've made this call {Club.clubDetail(item.id)} but it seems not working

The main app class:

  class App extends Component {
   render() {
return (
  <div className="App">
    <div className="App-left-side">
      <Clubs></Clubs>
    </div>
    <div className="App-center-side">
      <div className="App-center-side-content">
      <Club></Club>
      </div>
    </div>
  </div>
);
 }
 }

export default App;
1
  • You are trying to call Child to Parent that is not the correct way you have to pass the Onclickevent into props and use it , that is what composition will work Commented Jun 12, 2017 at 8:35

2 Answers 2

2

Since Clubs and Club components are used just to displace the data, so i will suggest to make the api call from App component, and pass the data to Clubs component along with an onClick function. Whenever user clicks on any item, pass the id to parent and displace the details of clicked item in Club component.

Like this:

App Component:

const clubsList = `urlto`;

class App extends Component {

    constructor(props) {
        super(props)
        this.state = {
            requestFailed: false,
            clubs: [],
            club: {}
        }
    }

    componentDidMount() {
        fetch(clubsList)
        .then(response => {
            if (!response.ok) {
                throw Error("Failed connection to the API")
            }
            return response
        })
        .then(response => response.json())
        .then(response => {
            this.setState({
                clubs: response
            })
        }, () => {
            this.setState({
                requestFailed: true
            })
        })
    }

    click = (id) => {
        console.log('clicked item', id);
    }

    render() {
        return (
            <div className="App">
                <div className="App-left-side">
                    <Clubs clubs={this.state.clubs} clicked={this.click}/>
                </div>
                <div className="App-center-side">
                    <div className="App-center-side-content">
                        <Club club={this.state.club}/>
                    </div>
                </div>
            </div>
        );
    }
}

export default App;

Clubs Component:

class Clubs extends Component {

    render() {
        if(!this.props.clubs.length) return <h1>No results</h1>

        return (
            <div>
                <ul>
                    {this.props.clubs.map((item) => {
                        return <a key={item.id} onClick={() => this.props.clicked(item.id)}>
                                  <li key={item.id}>{item.name}</li>
                              </a>
                    })}
                </ul>
            </div>
        );
    }
}

export default Clubs;

Club Component:

class Club extends Component {

    render() {
        if(!Object.keys(this.props.club)) return <h1>No club selected !</h1>;

        return (
            <ul>
                <li>Name : {this.props.club.name}</li>
                <li>Email : {this.props.club.email}</li>
                <li>Website : {this.props.club.website}</li>
            </ul>
        );
    }
}

export default Club;
Sign up to request clarification or add additional context in comments.

4 Comments

I got this error when i click on one of the items. TypeError: Cannot read property 'props' of undefined onClick src/clubs.js:15
i changed the map part, are you using the arrow function, like this: {this.props.clubs.map((item) => { check the clubs component and use it in the same way it should work.
In the clubs component you should make e.g : var props = this.props and change the onClick proprety onClick={() => props.clicked(item.id)}. Thanks dude
because this.props refer the the current element off the map loop
0

For reactjs to use another class you will need to export it:

export default class Club extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      name: '',
      password: ''
    };
  };
}

Remember that React.createClass has a built-in magic feature that bound all methods to this automatically for you. This can be a little confusing for JavaScript developers that are not used to this feature in other classes, or it can be confusing when they move from React to other classes.

The proper use of the feature:

class Clubs extends React.Component {
  Club = () => {
    ...
  }
  ...
}

Basically said:

export default class Club extends Component {

Is what you were forgetting to do and maybe the call to the class itself. Hope this solution might help you out!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.