TypeError: Cannot read properties of undefined (reading 'preventDefault') React

1.6k views Asked by At

Hi I am getting TypeError: Cannot read properties of undefined (reading 'preventDefault') on both my fetches. I have a usEffect that is being used to set the pagination. Which is where the problem seems to be but I'm not sure how I can solve this. When I remove the useEffect the search works but the pagination doesn't so I am a bit confused as to why I am getting the error.

Any help is appreciated.

Thanks

import React, {useState, useEffect} from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Alert, Col, Row, ListGroup, Container } from 'react-bootstrap';
import { MovieCard } from '../Components/MovieCard';
import { CustomPagination } from '../Components/CustomPagination';


export const Search = () => {
    const [page, setPage] = useState(1)
    const [numOfPages, setNumOfPages] = useState();
    const [query, setQuery] = useState("");
    const [movies, setMovies] = useState([]);
    const [show, setShow] = useState(true);
    // eslint-disable-next-line
    const [sayt, setSayt] = useState([]);
    
    const fetchResults = e => {
        e.preventDefault();
        setQuery(e.target.value);
        fetch(`https://api.themoviedb.org/3/search/movie?api_key=${process.env.REACT_APP_TMDB_KEY}&page=${page}&language=en-US&include_adult=false&query=${e.target.value}`
        )
        .then((res) => res.json())
        .then((data) => {
            if (!data.errors) {
                console.log(data)
                setSayt(data.results);   
            }else{
                <Alert variant="danger">Error</Alert>
            }
        })
    }
    
    const fetchSearch = e => {
        e.preventDefault();
        setQuery(e.target.value);
        fetch(`https://api.themoviedb.org/3/search/movie?api_key=${process.env.REACT_APP_TMDB_KEY}&page=${page}&language=en-US&include_adult=false&query=${e.target.value}`
        )
        .then((res) => res.json())
        .then((data) => {
            if (!data.errors) {
                console.log(data)
                setMovies(data.results);  
                setNumOfPages(data.total_pages); 
            }else{
                <Alert variant="danger">Error</Alert>
            }
        });
        setShow((s) => !s)
    }

    useEffect (()=>{
        fetchSearch();
        fetchResults();
        // eslint-disable-next-line
    }, [page]) 

    const saytShow = e => {
        setShow((s) => !s)
    }
    
    
    return (
        <div>
            <div className="search-container">
            <div className="row height d-flex justify-content-center align-items-center">
                <div className="col-xs-12 col-sm-12 col-md-8 col-lg-8 my-4">
                    <form fetchSearch={fetchSearch} value={query}>
                        <div className="search"> <i className="fa fa-search" onClick={saytShow}></i> 
                            <input 
                                type="text" 
                                className="form-control" 
                                placeholder="Search for a movie..." 
                                onChange={fetchResults}
                                onClick={saytShow}
                            /> 
                            {sayt.length > 0 && (
                                <ListGroup className="sayt" style={{ display: show ? "block" : "none" }}>
                                    {sayt.map(suggestions => (
                                        <ListGroup.Item action type="submit" onClick={fetchSearch} value={suggestions.title}>
                                            {suggestions.title}
                                        </ListGroup.Item>
                                    ))}
                                </ListGroup>
                            )}

                            <button type="submit" onClick={fetchSearch} value={query} className="search-button btn btn-primary">Search</button> 
                        </div>
                    </form>
                    
                </div>
            </div>
            </div>
            <Container fluid className="movie-grid">
                 {movies.length > 0 && (
                   <Row>
                       {movies.map(movieresults => (
                        <Col className="movie-grid" key={movieresults.id}>
                            <MovieCard movieresults={movieresults}/>
                        </Col>
                        ))}
                   </Row>    
                 )}
            </Container>
            <CustomPagination setPage={setPage} numOfPages={setNumOfPages} />

        </div>
        
        
    )
}
2

There are 2 answers

1
Vitaliy Rayets On BEST ANSWER

When you call fetchResults fetchSearch in useEffect you haven't event object. Just write correct conditions. Example:

const fetchResults = e => {
      e && e.preventDefault() && setQuery(e.target.value);
      fetch(`YOUR_URL?&query=${e ? e.target.value : query}`)
        .then((res) => res.json())
        .then((data) => {
            if (!data.errors) {
                console.log(data)
                setSayt(data.results);   
            }else{
                <Alert variant="danger">Error</Alert>
            }
        })
    }

the same with fetchSearch function

0
VSSSP On

Try change the button type from submit to button.

<button type="button" onClick={fetchSearch} value={query} className="search-button btn btn-primary">Search</button>

This way you don't need to prevent the default function of type submit.