Home > OS >  How to display search results using React Typescript?
How to display search results using React Typescript?

Time:12-04

This is the code for the interface:

export interface ActorAttributes {
    TYPE?: string,
    NAME?: string,
}

export interface MovieAttributes {
    OBJECTID: number,
    SID: string,
    NAME: string,
    DIRECTOR: string,
    DESCRIP: string,
}

App.tsx code:

import { useEffect, useState } from 'react';
import { searchMovies, searchActors, MovieAttributes, ActorAttributes } from "@utils/atts"

const Home: React.FC = () => {
    const [search, setSearch] = useState(false);
    const [movieSearch, setMovieSearch] = useState<MovieAttributes[]>([]);
    const [actorSearch, setActorSearch] = useState<ActorAttributes>([]);
    const [searchTerm, setSearchTerm] = useState('');

    useEffect(() => {
        if (searchTerm.length > 0) {
            setSearch(true);

            searchMovies(searchTerm).then(results => {
                setMovieSearch(results);
            });

            searchActors(searchTerm, movieSearch[1].SID).then(results => {
                setActorSearch(results);
            });

            setSearch(false);
        }
    }, [searchTerm, movieSearch]);

    const handleSearchTermChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setSearchTerm(event.target.value);
    }

    return (
        <div>
            <input type="text" value={searchTerm} onChange={handleSearchTermChange} />
            {search && <p>Searching...</p>}
            {movieSearch.length > 0 && <p>Found {movieSearch.length} movies</p>}
            {actorSearch.length > 0 && <p>Found {actorSearch.length} actors</p>}
        </div>
    );
}

So when a user searches a movie name or actor it's able to display the amount of movies and actors found but I'm curious on how I would display the data attributes (i.e. NAME, DIRECTOR, DESCRIP, etc.)

This is what I've tried so far, but it just displays errors stating that the movieAttributes doesn't contain toLowerCase() and I'm not quiet sure where to go from here or if I'm on the right track. I apologize in advance for the errors within my code as I am fairly new to react. If anyone has any tips, ideas, suggestions, etc. please feel free to leave a comment.

<div className="App">
     <ul className="posts">
     <input type="text" onChange={handleSearchTermChange} />
     {movieSearch.map((movieSearch) => {
          if (searchTerm == "" || movieSearch.toLowerCase().includes(searchTerm.toLowerCase())) {
             return (
                 <li key={movieSearch.OBJECTID}>
                 <h3>{movieSearch.NAME}</h3>
                 <p>{movieSearch.DIRECTOR}</p>
                 <p>{movieSearch.DESCRIP}</p>
                 </li>
             );
             }
                return null;
             )}
       </ul>
/div>

CodePudding user response:

There are some problems in your code.

  1. actorSearch state type should be ActorAttributes[].

  2. You should remove movieSearch from useEffect dependencies. Because each time the state gets updated, the useEffect gets executed but it's wrong.

  3. You're using movieSearch right after updating its value. It's wrong because set state functions in react are async. Instead, you should use another variable to hold the new movieSearch data in useEffect.

  4. In your .map function, you're using the same name as your state name (movieSearch) which is wrong.

  5. You're executing toLowerCase() on the MovieAttributes object but instead, you should do it on NAME property.

So hope this helps you:

import { useEffect, useState } from 'react';
import { searchMovies, searchActors, MovieAttributes, ActorAttributes } from "@utils/atts"

const Home: React.FC = () => {
    const [search, setSearch] = useState(false);
    const [movieSearch, setMovieSearch] = useState<MovieAttributes[]>([]);
    const [actorSearch, setActorSearch] = useState<ActorAttributes[]>([]);
    const [searchTerm, setSearchTerm] = useState('');

    useEffect(() => {
        if (searchTerm.length > 0) {
            setSearch(true);

            let newMovieSearch = [...movieSearch];

            searchMovies(searchTerm).then(results => {
                newMovieSearch = results;
                setMovieSearch(results);
            });

            searchActors(searchTerm, newMovieSearch[1].SID).then(results => {
                setActorSearch(results);
            });

            setSearch(false);
        }
    }, [searchTerm]);

    const handleSearchTermChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setSearchTerm(event.target.value);
    }

    return (
        <div>
            <input type="text" value={searchTerm} onChange={handleSearchTermChange} />
            {search && <p>Searching...</p>}
            {movieSearch.length > 0 && <p>Found {movieSearch.length} movies</p>}
            {actorSearch.length > 0 && <p>Found {actorSearch.length} actors</p>}
        </div>
    );
}
<div className="App">
     <ul className="posts">
        <input type="text" onChange={handleSearchTermChange} />
        {movieSearch.map((movie) => {
            if (searchTerm == "" || movie.NAME.toLowerCase().includes(searchTerm.toLowerCase())) {
                return (
                    <li key={movie.OBJECTID}>
                        <h3>{movie.NAME}</h3>
                        <p>{movie.DIRECTOR}</p>
                        <p>{movie.DESCRIP}</p>
                    </li>
                );
             }
            return null;
        )}
    </ul>
</div>
  • Related