Search code examples
reactjsapiweb-component

Render new react component based on API fetch


I'm trying to create a React app that will render components based on an API response (fetching topics title, description and the same for the courses that belong to them). The aim is to be able to add new topics and courses to the database, and not have to add any code to the front end for them to render.

import { Swiper, SwiperSlide } from 'swiper/react';                                                                                         
import Topic from './Topic.js';                                                                                                                                    
import 'swiper/swiper-bundle.min.css'                                                 
import 'swiper/swiper.min.css'                                                     
                                                                    
function Swiper() {                                      
   return (                                      
     <Swiper                                          
       spaceBetween={50}                                
       slidesPerView={1}                                 
       loop={true}                                
       direction={'horizontal'}                                
     >                                                  
       <SwiperSlide><Topic /></SwiperSlide>                                
     </Swiper>                                
   );                                
 };                                
                                 
 export default Swiper;   

  

I have this Swiper component, in which I will fetch a list of all Topics and populate the swiper with slides, based on the response.

Where I am having issues is, for each Topic, on a click event it needs to either:

  • open a new page and make a second API request listing all courses in that topic to populate that page. However this would require me to make a new page for each Topic manually and I'm trying to minimize having to update code on the front end.

  • or I could swap out the swiper component for the component which will display courses. However this method I need to make a second api request, and then pass that data up to the main app component so it can replace the Swiper with the new component. I'm not sure how to go about this.

Would be very grateful for any ideas on how I could achieve this, or if my assumptions on how to do this are accurate.

Thanks.


Solution

  • Would be very grateful for any ideas on how I could achieve this, or if my assumptions on how to do this are accurate.

    So this may not be the best way to implement something like what you want, but here is how I would approach it...

    open a new page and make a second API request listing all courses in that topic to populate that page. However this would require me to make a new page for each Topic manually and I'm trying to minimize having to update code on the front end.

    I would do this with a dynamic route, and use something like react-router to add a link like as follows:

    <Link to={`/topic/${topic.name`}>
     {topic.name}
    </Link>
    

    Then catch that route in my application with something like this:

    <Route path="/topic/:topicName" element={<Topic />}/>
    

    Now I need to create my topic page, and make sure we go fetch additional details about that topic before we render anything in that component, something like what i've put below might give you an idea. Also look at how useParams is used to pull the topicName out of the url path:

    const Topic = () => {
        const [loading, setLoading] = useState(true);
    
    
        const { topicName } = useParams();
        const [topic, setTopic] = useState(null);
    
        useEffect(() => {
          /**
           Add API Code here to fetch the topic, and when you get a response call
           setTopic(response.data) or something similar to set it locally.
    
           Also make sure you call setLoading(false);
          */
        }, []);
    
        if(loading){
            return (
             <h1>Loading Topic...</h1>
            )
        }
    
        if(topic){
            return (
                <div>
                 <h1>{topic.name}</h1>
                </div>
            );
        }
        return null;
    }
    
    

    Hopefully that will give you an idea on how you might do something like this, let me know if you want any more clarifications.