12

I call the function 'booksRefresh()' from the parent in the child component, but I get the error:

TypeError: booksRefresh is not a function

I don't know why, because 'booksRefresh' is a function. Can someone help me explain why this error occurs?

Here is my code:

import React, {useState} from "react";
import {Redirect} from "react-router";
import {addBook} from "../api/api";
import {Button} from "react-bootstrap";

const AddBookForm = (booksRefresh) => {
    const [title, setTitle] = useState();
    const [description, setDescription] = useState();
    const [submitted, setSubmitted] = useState(false);

    const postRequestHandler = () => {
        addBook(title, description);
        booksRefresh();
    }
...
 return (
        ...
            <Button type="submit" onClick={postRequestHandler} variant="outline-success">Add</Button>
        </div>
    )

Parent:

function App({history}) {
  ...
    const [changeInBooks, setChangeInBooks] = useState(0)

    const booksRefresh = () => {
        let incrementChangeInBook = changeInBooks + 1;
        setChangeInBooks(incrementChangeInBook)
    }
return (
        <div className="App">
            <header className="App-header">
                ...
                            <Button variant="outline-success" onClick={() => history.push("/new-book")}>
                                {ADD_BOOK}</Button>
                ...
            </header>
            <Switch>
                ...
                <Route path="/new-book" exact render={() =>
                    <AddBookForm
                        booksRefresh={booksRefresh}/>
                }/>
               ...
            </Switch>
        </div>
    );
}

export default withRouter(App);
wer
  • 201
  • 1
  • 3
  • 12

4 Answers4

17

The argument a React function component receives is its props, which is an object with named properties for each of the properties. So your AddBookForm's parameter shouldn't be booksRefresh, but (by convention) props, and then you use it via props.booksRefresh():

const AddBookForm = (props) => {
// −−−−−−−−−−−−−−−−−−^^^^^
    const [title, setTitle] = useState();
    const [description, setDescription] = useState();
    const [submitted, setSubmitted] = useState(false);

    const postRequestHandler = () => {
        addBook(title, description);
        props.booksRefresh();
// −−−−−^^^^^^
    }

    // ...

Or if it's the only prop, you can use destructuring as adiga shows:

const AddBookForm = ({booksRefresh}) => {
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
4

The props parameter is an object with a property called booksRefresh inside it.

Use destructuring to get the property

const AddBookForm = ({ booksRefresh }) => {

}

You are already doing it to get history in the App component

adiga
  • 34,372
  • 9
  • 61
  • 83
4
const AddBookForm = ({booksRefresh}) => {
        const [title, setTitle] = useState();
        const [description, setDescription] = useState();
        const [submitted, setSubmitted] = useState(false);

        const postRequestHandler = () => {
            addBook(title, description);
            booksRefresh();
        }

try this i hope it works

because of props.booksRefresh is a function

Man
  • 742
  • 1
  • 6
  • 23
3

Because first argument of functional component is props

function Component(props) {
}

You have to retrieve prop by name

function Component(props) {
 const prop = props.propName
}

Or using destructuring

function Component({propName) {
}
bapafes482
  • 444
  • 4
  • 18