I have used Redux for state management in my application - with React Hooks. I am able to hit the API and get the response back like below screenshots from my action creator logs:
Here's the code of my component where I'm trying to display the results:
import { useState, useEffect } from "react";
import {Link} from 'react-router-dom';
import styled from "styled-components";
import {GoSearch} from 'react-icons/go';
import LoaderSpinner from "../components/LoaderSpinner";
import MovieItem from "../components/MovieItem";
import { RootStateOrAny, useDispatch, useSelector } from "react-redux";
import {fetchAllShows} from '../actions/movies';
import {searchMovieByTitle} from '../actions/search';
const Home = () => {
const [loading, setLoading] = useState(true);
const [searchString, setSearchString] = useState('');
const [isFromSearchResults, setIsFromSearchResults] = useState(false);
const dispatch = useDispatch();
const movies = useSelector((state: RootStateOrAny) => state.shows)
const searchResults = useSelector((state: RootStateOrAny) => state.shows);
useEffect(()=> {
setLoading(true);
dispatch(fetchAllShows());
setIsFromSearchResults(false);
}, [dispatch])
const handleSearchChange = (e: any) => {
e.preventDefault();
setSearchString(e.target.value);
}
const findMovieByTitle = () => {
dispatch(searchMovieByTitle(searchString));
setIsFromSearchResults(true);
setSearchString('');
}
console.log(isFromSearchResults);
var start, max, paginatedArr=[], pageSize = 25;
for(start = 0; max = movies.length, start < max; start += pageSize) {
paginatedArr = movies.slice(start, start + pageSize);
}
return <HomeContainer>
<div className="search-bar">
<input
type="text"
placeholder="Search for a movie"
value={searchString}
onChange={handleSearchChange}
/>
<div className="search" onClick={findMovieByTitle}>
<GoSearch />
</div>
</div>
<div className="grid">
{
isFromSearchResults
? <div>
{
searchResults.map((result: any, index: number) => {
console.log(result);
// console.log(result.show);
return <Link
key={index}
to={{pathname:`/movies/${result.show.id}`,
state: {movie: result.show}}}
>
<MovieItem show={result.show} />
</Link>
})
// errors out in this return statement. It says the result (from array mapped out above is null) whereas the action creator is able to print out the full search queries
}
</div>
: movies.length == 0
? <div className="loader">
<LoaderSpinner
isLoading={loading}
loadingText="Fetching Movies..."
/>
</div>
// : movies.map((movie:any, index:number) => {
: paginatedArr.map((movie:any, index:number) => {
return <Link
to={{pathname:`/movies/${movie.id}`,
state: {movie: movie}}} key={index}
>
<MovieItem show={movie} />
</Link>
})
}
</div>
</HomeContainer>
}
export default Home;
Here's the code for my action creator to make the search API call:
import {
SEARCH_MOVIE_BY_TITLE,
} from './types';
import ShowsService from '../services/ShowsService';
export const searchMovieByTitle = (title: string) => async (dispatch: any) => {
try {
let response = await ShowsService.searchMovieByTitle(title);
console.log(typeof(response.data));
// console.log(response.data);
const promise = response.data.map((items: any) => {
// console.log(items);
return items;
})
const searchArr = await Promise.all(promise);
console.log(searchArr);
dispatch({type: SEARCH_MOVIE_BY_TITLE, payload: searchArr});
} catch (err) {
console.log(err);
}
}
The problem now lies in trying to parse the search results array and display it as a list of <MyComponent /> with movie passed as props. It shows undefined for each of the items passed. How do I resolve this?
Sample error log attached below:


const movies = useSelector((state: RootStateOrAny) => state.shows); const searchResults = useSelector((state: RootStateOrAny) => state.shows)looks sketchy - you're accessing the same state twice under different names. Have you confirmed that these arrays (which hold the data that is rendered) contain the expected data?const promise = response.data.map((items: any) => { return items; }); const searchArr = await Promise.all(promise);is pointless if that's all you're doing in that loop. Simplify toconst searchArr = response.data;..showsproperty on the items, while the other code assumes the movie objects are stored directly in the array. Decide on one, then abstract that part into a helper function that you can call twice.