I have a searchbar component that I used context to import into another component. The state of the searchbar in its own component works but when I use the context to import it to another component it does not work. I have used other contexts in my project and they have worked but the searchbar state doesn't. I have no idea where to start, or how to go about fixing it. Can someone point me in the right direction?
export const SearchInput = () => {
const [searchInput, setSearchInput] = useState('');
const handleSubmit = (e) => {
e.preventDefault()
}
return (
<div>
<form onSubmit={handleSubmit}>
<input type='text'
className='search-input'
name='search-movies'
value={searchInput}
onChange={(e) => setSearchInput(e.target.value)} />
</form>
</div>
)
}
//Use Context Component
export const SearchContext = React.createContext()
export function SearchProvider({ children }) {
const [searchInput, setSearchInput] = useState('');
const value = {
searchInput
}
return (
<div>
<SearchContext.Provider value={value}>
{children}
</SearchContext.Provider>
</div>
)
}
const Movies = () => {
const { data, loading, isErr } = useFetch([
`https://api.themoviedb.org/3/list/7077601?api_key=${process.env.REACT_APP_API_KEY}&language=en-US`,
`https://api.themoviedb.org/3/list/7078334?api_key=${process.env.REACT_APP_API_KEY}&language=en-US`,
`https://api.themoviedb.org/3/list/7078244?api_key=${process.env.REACT_APP_API_KEY}&language=en-US`
]);
const { watchList, handleClick } = useContext(WatchListContext);
const { searchInput } = useContext(SearchContext)
const [moviePoster, setmoviePoster] = useState(`giphy (1).gif`);
const [movieTitle, setmovieTitle] = useState('');
const [movieDescription, setmovieDescription] = useState('')
const styles = {
backgroundImage: `url(${moviePoster})`
};
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y]);
return (
<div className='movie-container'>
{isErr && <div className="error">{isErr}</div>}
{loading && <Spinner animation="border" variant="secondary" className="spinner" >
<span>Loading...</span>
</Spinner>}
<div className='movie-hero' style={styles}></div>
<div className="contains-descriptions">
<h2 className="hero-movie-title show-movie">{movieTitle}</h2>
<p className="hero-movie-description show-movie">{movieDescription}</p>
</div>
<section className="movies">
<h2 style={{ color: 'white', marginLeft: '20px' }}>Action </h2>
{data && <Swiper
spaceBetween={10}
slidesPerView={6}
pagination={{ clickable: true }}
scrollbar={{ draggable: true }}
onSlideChange={() => console.log('slide change')}
onSwiper={(swiper) => console.log(swiper)}
>
{data && data[0].items.map(movie =>
<SwiperSlide key={movie.id}>
<div className='movie' >
<img onMouseOver={() => {
setmoviePoster(`${"https://image.tmdb.org/t/p/original" + movie.poster_path}`);
setmovieTitle(movie.original_title);
setmovieDescription(movie.overview);
}}
src={'https://image.tmdb.org/t/p/original' + movie.poster_path} width='250' height='300'
alt='Promotional Poster For Movie'
/>
<button className="watchlist-btn"
onClick={() => handleClick(movie.original_title)}>
{watchList.includes(movie.original_title) ?
<i className="fas fa-minus-circle"></i> :
<i className="fas fa-plus-circle"></i>}
</button>
</div>
</SwiperSlide>
)
}
</Swiper>}
</section>
I'm assuming a component tree that looks something like this:
+-- SearchProvider
| +-- SearchInput
| +-- Movies
Your SearchProvider
should be providing both the state and the state setter as its value:
export const SearchContext = React.createContext()
export function SearchProvider({ children }) {
const [searchInput, setSearchInput] = useState('');
const value = {
searchInput,
setSearchInput
};
return ...
}
Your SearchInput
should no longer be controlling its own local state. That state now has to be shared with the rest of the tree. Instead, it subscribes to the context and updates it directly:
export const SearchInput = () => {
const { searchInput, setSearchInput } = React.useContext(SearchContext);
const handleSubmit = (e) => {
e.preventDefault()
};
return ...
}
Why are you using context and not just useState and props?
I think it would work with something like the following:
export const SearchInput = (props) => {
const handleSubmit = (e) => {
e.preventDefault()
}
return (
<div>
<form onSubmit={handleSubmit}>
<input type='text'
className='search-input'
name='search-movies'
value={props.value}
onChange={(e) => props.onChange(e.target.value)} />
</form>
{props.children}
</div>
)
}
export function SearchCompoent({ children }) {
const [searchInputValue, setSearchInputValue] = useState('');
return (
<SearchInput value={searchInputValue}>
{children}
</SearchInput>
)
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.