Ryuk
Ryuk

Reputation: 372

How to render a component on Click on list item to show its detail?

I have a Dashboard component that is fetching all city data from an API and store it in the cities state. Now I want that when a city name is clicked a new page opens having all the props of the clicked city.

function Dashboard() {
    const [cities, setcities] = useState(null);

    useEffect(() => {
        axios.get('http://localhost:2000/city/')
            .then(res => {
                console.log(res);
                setcities(res.data);
            });
    }, []);

    const handleClick = (e) => {
         // Here I want to show a detail page of the clicked item //
        // <DetailsPage city={e} />
    }

    return (
        <div >

            <div>Dashboard</div>

            <ul className="list-group list-group-flush">
                {cities !== null ?
                    cities.map(city => {
                        return (
                            <li className="list-group-item" key={city._id} onClick={() => handleClick(city)}>
                                {city.City}
                            </li>

                        );
                    }) :
                    null
                }
            </ul>
            {console.log(cities)}

        </div>
    );
}

Upvotes: 0

Views: 1812

Answers (1)

Hossein Moradi
Hossein Moradi

Reputation: 598

If you like to show the details under the selected city you can keep it in your component state and render it conditionally:

function Dashboard() {
    const [selectedCity, setSelectedCity] = useState(null);
    const [cities, setcities] = useState(null);

    useEffect(() => {
        axios.get('http://localhost:2000/city/')
            .then(res => {
                console.log(res);
                setcities(res.data);
            });
    }, []);

    const handleClick = (e) => {
        setSelectedCity(e)
    }

    return (
        <div >

            <div>Dashboard</div>

            <ul className="list-group list-group-flush">
                {cities !== null ?
                    cities.map(city => {
                        return (
                            <li className="list-group-item" key={city._id} onClick={() => handleClick(city)}>
                                {city.City}
                                {selectedCity === city ? <DetailsPage city={city} /> : null}
                            </li>

                        );
                    }) :
                    null
                }
            </ul>
            {console.log(cities)}

        </div>
    );
}


If you want to only show the selected city content (with probably a back button):

function Dashboard() {
    const [selectedCity, setSelectedCity] = useState(null);
    const [cities, setcities] = useState(null);

    useEffect(() => {
        axios.get('http://localhost:2000/city/')
            .then(res => {
                console.log(res);
                setcities(res.data);
            });
    }, []);

    const handleClick = (e) => {
        setSelectedCity(e)
    }

    if (selectedCity) {
        return <DetailsPage city={e} onBack={() => setSelectedCity(null)} />
    }

    return (
        <div >

            <div>Dashboard</div>

            <ul className="list-group list-group-flush">
                {cities !== null ?
                    cities.map(city => {
                        return (
                            <li className="list-group-item" key={city._id} onClick={() => handleClick(city)}>
                                {city.City}
                            </li>

                        );
                    }) :
                    null
                }
            </ul>
            {console.log(cities)}

        </div>
    );
}


If you want a separate page with a different URL, it will be more complex than this.

    const handleClick = (e) => {
        history.push("/city", { id: e.id });
    }
  • You have to read the data on both pages. So you may need to put your cities and the selected city values in a React Context so that you can use it on the details page. Alternatively, you can fetch the data on the parent component and move these states to it, so that you can pass the values to both pages.
  • If you fetch data on the Dashboard page, you should also handle the scenario in which a user refreshes the details page or enters the URL directly. You may need a different API to fetch a city by its ID. Alternatively, you can simply redirect to the Dashboard page if you are on the details page and you don't have the required data.

Upvotes: 2

Related Questions