简体   繁体   English

State 不在不同的组件中更新

[英]State not updating in different component

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.搜索栏的 state 在其自己的组件中有效,但是当我使用上下文将其导入另一个组件时,它不起作用。 I have used other contexts in my project and they have worked but the searchbar state doesn't.我在我的项目中使用了其他上下文并且它们有效,但搜索栏 state 没有。 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:您的SearchProvider应该同时提供 state 和 state 设置器作为其值:

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.您的SearchInput不应再控制其自己的本地 state。 That state now has to be shared with the rest of the tree. state 现在必须与树的 rest 共享。 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?为什么你使用上下文而不只是 useState 和 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>
    )
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM