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.
actorSearch state type should be
ActorAttributes[]
.You should remove
movieSearch
from useEffect dependencies. Because each time the state gets updated, the useEffect gets executed but it's wrong.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 newmovieSearch
data in useEffect.In your
.map
function, you're using the same name as your state name (movieSearch
) which is wrong.You're executing
toLowerCase()
on theMovieAttributes
object but instead, you should do it onNAME
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>