Search code examples
reactjstypescriptreact-props

passing props to functional component


i can't seem to pass any props from my parent to my functional component. I get the value from a query string parameter or cookie then just pass it through but it dosen't seem to work in my very basic use case. My parent is

import React, { useState, useEffect } from 'react';
import './App.css';
import { Helmet } from 'react-helmet';
import Cookies from "universal-cookie";
import Navbar from './components/Navbar';
import Footer from './components/Footer';
import Home from './components/Home';
import { IBookmaker } from './interfaces/IBookmaker';

function App() {
    const cookies = new Cookies();
    const query = new URLSearchParams(window.location.search)
    var bookmakerid = Number(query.get('bid'));
    if (bookmakerid && bookmakerid > 0) {
        cookies.set("bid", bookmakerid)
    }
    else {
        if (cookies.get('bid') && Number(cookies.get('bid')) > 0) {
            bookmakerid = Number(cookies.get('bid'));
        }
    }    

return (
         <div className="App">           
            <Helmet>

            </Helmet>
            <Navbar ></Navbar>
            <div className="page bg-gray-100">
                <section className="section section-variant-1 bg-gray-100">
                     <Home bookmakerid={bookmakerid} />
                </section>
            </div>
            <Footer />
        </div>
     );
}

My child "Home" component is

import React, { useEffect, useState, } from 'react';
import "../App.css";
import { ICompetition } from '../interfaces/ICompetition';

function Home({ bookmakerid }) {
    const [compList, setData] = useState<ICompetition | null>(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        fetch("http://localhost:5242/GetCompetitions?bid=" + bookmakerid, { method: "GET" })
            .then(response => {
                if (response.ok) {
                    console.log(response);
                    //return response.json();
                }
            })
            //.then(data => {
            //    setData(data);
            //})
            //.catch(err => {
            //    setError(err)
            //});
    }, []);

    return (
        <section className="section section-variant-1 bg-gray-100">
            <div className="isotope-item" data-filter="football">
                    <div className="sport-table">
                        <div className="sport-table-tr">
                            <div id="runnerContainer" className="carousel-inner">                            
                        </div>
                    </div>
                </div>
            </div>
        </section>
);
}

If there is a querystring/cookie value it does populate the bookmakerid but in home i always get "Binding element 'bookmakerid' implicitly has an 'any' type."

Also if i try to define my Home component with props function Home(props) { (to try props.bookmakerid) I get Binding element 'props' implicitly has an 'any' type.

Every example i look at online it just seems to work in a very similar way that i'm attempting it here. This video for example https://www.youtube.com/watch?v=kHJSNFU7H4U&t=580s. Just can't see how my code is different. I'm using Visual studio 2022 with the standard react typescript template. Thanks.


Solution

  • As you are using typescript, you need to declare the type of your arguments, the props in this case, otherwise you will get this kind of error.

    Looking at the code for App the bookmakerId seems to be a number, so this should do the trick:

    import React, { useEffect, useState, } from 'react';
    import "../App.css";
    import { ICompetition } from '../interfaces/ICompetition';
    
    interface HomeProps {
        bookmakerid: number;
    }
    
    function Home({ bookmakerid }: HomeProps) {
        const [compList, setData] = useState<ICompetition | null>(null);
        const [loading, setLoading] = useState(true);
        const [error, setError] = useState(null);
    
        useEffect(() => {
            fetch("http://localhost:5242/GetCompetitions?bid=" + bookmakerid, { method: "GET" })
                .then(response => {
                    if (response.ok) {
                        console.log(response);
                        //return response.json();
                    }
                })
                //.then(data => {
                //    setData(data);
                //})
                //.catch(err => {
                //    setError(err)
                //});
        }, []);
    
        return (
            <section className="section section-variant-1 bg-gray-100">
                <div className="isotope-item" data-filter="football">
                        <div className="sport-table">
                            <div className="sport-table-tr">
                                <div id="runnerContainer" className="carousel-inner">                            
                            </div>
                        </div>
                    </div>
                </div>
            </section>
    );
    }
    

    Note that you concatenate this number to the fetch URL, that is not exactly pure as string + number means the number is implicitly cast to a string, but it should work. I would consider explicitly casting though if you want to make sure, or probably even better to treat the bookmakerid as a string as you probably do not want to do arithmetic with it.