1

A have an array objects in React JS and I want to loop through it.

My code is as follows :

let data = [
    {make: "Volkswagen", models: ["Golf", "Passat", "Polo", "Tiguan"]},
    {make: "Skoda", models: ["Fabia", "Octavia", "Superb"]},
    {make: "Audi", models: ["A1", "A3", "A5", "Q3", "Q5"]}
];    

export default class makeModel extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            show: false,
            make: null
        }
    }

    handleMake(event){
        event.preventDefault();
        this.setState({make: event.target.name, show: !this.state.show});
    }

    render() {
        const language = this.props.language;
        let style = {display: "none"};

        if(this.state.show) style = {display: "block"};
        return (
            <div>
                <div className="priceTitle">{language.makeAndModel}</div>
                {data.map( (car, i) => {
                    return (
                        <div key={i} className="makeModel">
                            <Link to="/" className="make" name={car.make} onClick={this.handleMake.bind(this)}>{car.make}</Link>
                            <div className="models" style={style}>
                                {car.models.map((m, i) => {
                                    if(car.models.indexOf(m) > -1 && car.make === this.state.make){
                                        return <div key={i}>{m}</div>
                                    }
                                })}
                            </div>
                        </div>
                    )
                })}
            </div>
        );
    }
}

I want to show the list of all makes. And then on click I want to show than all models of that make.

My code works. But onClick there are all three divs with class models shown. But only in the clicked one the models are shown. How to hide all those div's with class model and show only the clicked one?

And generally, is there any better way to do it?

2
  • 2
    Make your components as small as possible, it makes it lots easier to handle state changes. If you don't want to show something, you could also return null instead of using a style change. The onClick handler could be given through as a prop, and also the current brand could be given as a prop. So you could split your components in BrandList, which renders then a BrandComponent, which renders a ModelList, which renders a Model. Current Brand can be in the state of the BrandLIst, current model in the state of the ModelList, and those states can be given through as prop Commented Sep 5, 2016 at 13:21
  • More info you could also find here: medium.com/@dan_abramov/… Commented Sep 5, 2016 at 13:22

1 Answer 1

2

Try this :

import React from 'react';

let data = [
{make: "Volkswagen", models: ["Golf", "Passat", "Polo", "Tiguan"]},
{make: "Skoda", models: ["Fabia", "Octavia", "Superb"]},
{make: "Audi", models: ["A1", "A3", "A5", "Q3", "Q5"]}
];

const ModelLink = ({models,make,handleMake,isDisplay}) => {

const modelList = isDisplay ? models.map((m, i) =>  <div key={i}>{m}</div>) : "";

return (
     <div className="makeModel">
            <h3 to="/" className="make" name={make} onClick={handleMake}>{make}</h3>
            <div className="models" >
                {modelList}
            </div>
     </div>
)

}

export default class makeModel extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        selectedMake: null
    }
}

handleMake(event,name){
    event.preventDefault();

    const nextMake = this.state.selectedMake !== name ? name : null;

    this.setState({selectedMake: nextMake});
}

render() {
    const {selectedMake} = this.state;
    return (
        <div>
            {data.map((car, i) => {
                return (
                    <ModelLink key={i} 
                            models={car.models} 
                            make={car.make} 
                            isDisplay={car.make === selectedMake} 
                            handleMake={(e) => this.handleMake(e,car.make)} 
                    />
                )
            })}
        </div>
    );
}
}
Sign up to request clarification or add additional context in comments.

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.