Javascript 如何在搜索输入中实现全局状态,从而使用ContextAPI跨选项卡保存搜索词
好的,我这里有一个问题,我不熟悉React的打字脚本,所以我有点困惑。 当我输入,比如说,搜索电影输入时,我想做一个全局搜索词,我想保存那个状态(搜索词),并将它提供给搜索电视节目输入 所以我发现我必须有两个跨组件的搜索输入。接下来,我制作了一个ContextAPI文件,它只提供搜索状态上下文,我有两个文件,MoviesContext和TVShowsContext,可以在其中找到主状态,用于数据获取,在键入searchTerm时过滤搜索 我拥有的组件有:电影、电视节目和搜索,它基本上为电影和电视节目组件提供输入 这里的代码,如果我没有解释好,请在下面的评论,我会尝试修复它 背景: SearchContext.tsxJavascript 如何在搜索输入中实现全局状态,从而使用ContextAPI跨选项卡保存搜索词,javascript,reactjs,typescript,state,context-api,Javascript,Reactjs,Typescript,State,Context Api,好的,我这里有一个问题,我不熟悉React的打字脚本,所以我有点困惑。 当我输入,比如说,搜索电影输入时,我想做一个全局搜索词,我想保存那个状态(搜索词),并将它提供给搜索电视节目输入 所以我发现我必须有两个跨组件的搜索输入。接下来,我制作了一个ContextAPI文件,它只提供搜索状态上下文,我有两个文件,MoviesContext和TVShowsContext,可以在其中找到主状态,用于数据获取,在键入searchTerm时过滤搜索 我拥有的组件有:电影、电视节目和搜索,它基本上为电影和电视
import React, { createContext, FC, useState } from 'react'
export const SearchContext = createContext(null)
export const SearchContextProvider: FC = ({ children }) => {
const [searchTerm, setSearchTerm] = useState('')
return (
<SearchContext.Provider value={{ searchTerm, setSearchTerm }}>
{children}
</SearchContext.Provider>
)
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import axios from 'axios';
import { discoverMoviesEndpoint, searchMoviesEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string
loading: boolean
}
export const MovieContext = createContext(null)
export const MovieContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.currentTarget.value
setState((prevState: any) => ({ ...prevState, query }))
if (query.length > 0) {
setTimeout(() => {
axios(`${searchMoviesEndpoint}` + query)
.then(({ data }) => {
let results = data.results
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, query, suggestions, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchMovies()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchMovies = (): void => {
axios(`${discoverMoviesEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log("%c Results", 'color: blue', data.results)
setState((prevState) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
const error = new Error('Oops, there has been some internal server error.')
alert(error)
}
if (err.request) {
const error = new Error('Oops, there has been some network error.')
alert(error)
} else {
window.alert(`Oops, ${err.message}`)
}
})
}
return (
<MovieContext.Provider value={{ state, setState, fetchMovies, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</MovieContext.Provider>
);
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { discoverTVShowsEndpoint, searchShowsEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string,
loading: boolean
}
export const TVShowsContext = createContext(null)
export const TVShowsContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.target.value
setState((prevState: any) => ({ ...prevState, query })) // this is making sure that onChange will fire
if (query.length > 0) {
setTimeout(() => {
axios(`${searchShowsEndpoint}` + query)
.then(({ data }) => {
let results = data.results
console.log(results)
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, suggestions, query, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchTVShows()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchTVShows = (): void => {
axios(`${discoverTVShowsEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log(popularResults)
setState((prevState: any) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}
const suggestionSelected = (value: string) => {
setState((prevState: any) => ({ ...prevState, query: value, suggestions: [] }))
}
const renderSuggestedSearch = () => {
if (suggestions.length !== 0) {
return (
<ul>
{suggestions.map((item: any, idx: number) => (
<Link to="/movie-details"><li className="suggestions" onClick={() => suggestionSelected(item.name)} key={idx}>{item.name}</li></Link>
))}
</ul>
)
} else {
return null
}
}
const popularResultsRender = popularResults.slice(0, 10).map((item: any, index: any) => {
return (
<div className="card" key={index}>
<img className="image" alt="cover" src={`http://image.tmdb.org/t/p/w300/${item.poster_path}`} />
<h1 className="title"><a href="https">{item.name}</a></h1>
<p className="overview">{item.overview}</p>
</div>
)
})
return (
<TVShowsContext.Provider value={{ state, setState, fetchTVShows, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</TVShowsContext.Provider>
);
}
import React,{createContext,FC,useState}来自“React”
export const SearchContext=createContext(null)
export const SearchContextProvider:FC=({children})=>{
常量[searchTerm,setSearchTerm]=useState(“”)
返回(
{儿童}
)
}
MoviesContext.tsx
import React, { createContext, FC, useState } from 'react'
export const SearchContext = createContext(null)
export const SearchContextProvider: FC = ({ children }) => {
const [searchTerm, setSearchTerm] = useState('')
return (
<SearchContext.Provider value={{ searchTerm, setSearchTerm }}>
{children}
</SearchContext.Provider>
)
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import axios from 'axios';
import { discoverMoviesEndpoint, searchMoviesEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string
loading: boolean
}
export const MovieContext = createContext(null)
export const MovieContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.currentTarget.value
setState((prevState: any) => ({ ...prevState, query }))
if (query.length > 0) {
setTimeout(() => {
axios(`${searchMoviesEndpoint}` + query)
.then(({ data }) => {
let results = data.results
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, query, suggestions, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchMovies()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchMovies = (): void => {
axios(`${discoverMoviesEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log("%c Results", 'color: blue', data.results)
setState((prevState) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
const error = new Error('Oops, there has been some internal server error.')
alert(error)
}
if (err.request) {
const error = new Error('Oops, there has been some network error.')
alert(error)
} else {
window.alert(`Oops, ${err.message}`)
}
})
}
return (
<MovieContext.Provider value={{ state, setState, fetchMovies, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</MovieContext.Provider>
);
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { discoverTVShowsEndpoint, searchShowsEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string,
loading: boolean
}
export const TVShowsContext = createContext(null)
export const TVShowsContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.target.value
setState((prevState: any) => ({ ...prevState, query })) // this is making sure that onChange will fire
if (query.length > 0) {
setTimeout(() => {
axios(`${searchShowsEndpoint}` + query)
.then(({ data }) => {
let results = data.results
console.log(results)
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, suggestions, query, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchTVShows()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchTVShows = (): void => {
axios(`${discoverTVShowsEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log(popularResults)
setState((prevState: any) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}
const suggestionSelected = (value: string) => {
setState((prevState: any) => ({ ...prevState, query: value, suggestions: [] }))
}
const renderSuggestedSearch = () => {
if (suggestions.length !== 0) {
return (
<ul>
{suggestions.map((item: any, idx: number) => (
<Link to="/movie-details"><li className="suggestions" onClick={() => suggestionSelected(item.name)} key={idx}>{item.name}</li></Link>
))}
</ul>
)
} else {
return null
}
}
const popularResultsRender = popularResults.slice(0, 10).map((item: any, index: any) => {
return (
<div className="card" key={index}>
<img className="image" alt="cover" src={`http://image.tmdb.org/t/p/w300/${item.poster_path}`} />
<h1 className="title"><a href="https">{item.name}</a></h1>
<p className="overview">{item.overview}</p>
</div>
)
})
return (
<TVShowsContext.Provider value={{ state, setState, fetchTVShows, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</TVShowsContext.Provider>
);
}
import React,{ChangeEvent,useState,createContext,useContext,FC}来自'React';
从“axios”导入axios;
从“../../utils/api”导入{discoverMoviesEndpoint,searchMoviesEndpoint}
从“./SearchContext”导入{SearchContext};
类型InputElement=ChangeEvent
界面状态{
流行结果:[],
建议:[],
查询:字符串
加载:布尔值
}
export const MovieContext=createContext(null)
导出常量MovieContextProvider:FC=({children})=>{
const{searchTerm,setSearchTerm}=useContext(SearchContext)
常量[状态,设置状态]=使用状态({
流行结果:[],
建议:[],
查询:searchTerm,
加载:false,
})
常量{popularResults,suggestions}=状态
常量handleSearchInput=(e:InputElement):void=>{
const query=e.currentTarget.value
setState((prevState:any)=>({…prevState,query}))
如果(query.length>0){
设置超时(()=>{
axios(`${searchMoviesEndpoint}`+查询)
。然后({data})=>{
让结果=data.results
让建议=结果。切片(0,10)
如果(query.length>2){
const regex=new RegExp(`^${query}`,'i')
建议.sort((prop:any)=>prop.release\u date)。filter((val:any)=>regex.test(val))
setState((prevState:any)=>({…prevState,查询,建议,加载:false,popularResults:[]))
setSearchTerm((prevQuery:any)=>({…prevQuery,query}))
}否则{
电影(
setState((prevState:any)=>({…prevState,建议:[]}))
setState((prevState:any)=>({…prevState,建议:[]}))
}
})
.catch((错误)=>{
如果(错误响应){
log('Oops,似乎有服务器错误',err)
控制台跟踪(错误)
window.alert(`Oops,${err}`)
}
如果(错误请求){
log('Oops,似乎有网络错误',err)
控制台跟踪(错误)
window.alert(`Oops,${err}`)
}
})
}, 1000)
}返回空值
}
常量fetchMovies=():void=>{
axios(`${DiscoveryMoviesEndpoint}`)
。然后({data})=>{
让popularResults=data.results
console.log(“%c Results”、“color:blue”、data.Results)
setState((prevState)=>({…prevState,popularResults}))
})
.catch((错误)=>{
如果(错误响应){
const error=new error('Oops,出现了一些内部服务器错误')
警报(错误)
}
如果(错误请求){
const error=new error('Oops,出现了一些网络错误')
警报(错误)
}否则{
window.alert(`Oops,${err.message}`)
}
})
}
返回(
{儿童}
);
}
TVShowsContext.tsx
import React, { createContext, FC, useState } from 'react'
export const SearchContext = createContext(null)
export const SearchContextProvider: FC = ({ children }) => {
const [searchTerm, setSearchTerm] = useState('')
return (
<SearchContext.Provider value={{ searchTerm, setSearchTerm }}>
{children}
</SearchContext.Provider>
)
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import axios from 'axios';
import { discoverMoviesEndpoint, searchMoviesEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string
loading: boolean
}
export const MovieContext = createContext(null)
export const MovieContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.currentTarget.value
setState((prevState: any) => ({ ...prevState, query }))
if (query.length > 0) {
setTimeout(() => {
axios(`${searchMoviesEndpoint}` + query)
.then(({ data }) => {
let results = data.results
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, query, suggestions, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchMovies()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchMovies = (): void => {
axios(`${discoverMoviesEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log("%c Results", 'color: blue', data.results)
setState((prevState) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
const error = new Error('Oops, there has been some internal server error.')
alert(error)
}
if (err.request) {
const error = new Error('Oops, there has been some network error.')
alert(error)
} else {
window.alert(`Oops, ${err.message}`)
}
})
}
return (
<MovieContext.Provider value={{ state, setState, fetchMovies, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</MovieContext.Provider>
);
}
import React, { ChangeEvent, useState, createContext, useContext, FC } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import { discoverTVShowsEndpoint, searchShowsEndpoint } from '../../utils/api'
import { SearchContext } from './SearchContext';
type InputElement = ChangeEvent<HTMLInputElement>
interface IState {
popularResults: [],
suggestions: [],
query: string,
loading: boolean
}
export const TVShowsContext = createContext(null)
export const TVShowsContextProvider: FC = ({ children }) => {
const { searchTerm, setSearchTerm } = useContext(SearchContext)
const [state, setState] = useState<IState>({
popularResults: [],
suggestions: [],
query: searchTerm,
loading: false,
})
const { popularResults, suggestions } = state
const handleSearchInput = (e: InputElement): void => {
const query = e.target.value
setState((prevState: any) => ({ ...prevState, query })) // this is making sure that onChange will fire
if (query.length > 0) {
setTimeout(() => {
axios(`${searchShowsEndpoint}` + query)
.then(({ data }) => {
let results = data.results
console.log(results)
let suggestions = results.slice(0, 10)
if (query.length > 2) {
const regex = new RegExp(`^${query}`, 'i')
suggestions.sort((prop: any) => prop.release_date).filter((val: any) => regex.test(val))
setState((prevState: any) => ({ ...prevState, suggestions, query, loading: false, popularResults: [] }))
setSearchTerm((prevQuery: any) => ({ ...prevQuery, query }))
} else {
fetchTVShows()
setState((prevState: any) => ({ ...prevState, suggestions: [] }))
}
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}, 1000)
} return null
}
const fetchTVShows = (): void => {
axios(`${discoverTVShowsEndpoint}`)
.then(({ data }) => {
let popularResults = data.results
console.log(popularResults)
setState((prevState: any) => ({ ...prevState, popularResults }))
})
.catch((err) => {
if (err.response) {
console.log('Oops, it seems there\'s a server error. ', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
if (err.request) {
console.log('Oops, it seems there\'s a network error.', err)
console.trace(err)
window.alert(`Oops, ${err}`)
}
})
}
const suggestionSelected = (value: string) => {
setState((prevState: any) => ({ ...prevState, query: value, suggestions: [] }))
}
const renderSuggestedSearch = () => {
if (suggestions.length !== 0) {
return (
<ul>
{suggestions.map((item: any, idx: number) => (
<Link to="/movie-details"><li className="suggestions" onClick={() => suggestionSelected(item.name)} key={idx}>{item.name}</li></Link>
))}
</ul>
)
} else {
return null
}
}
const popularResultsRender = popularResults.slice(0, 10).map((item: any, index: any) => {
return (
<div className="card" key={index}>
<img className="image" alt="cover" src={`http://image.tmdb.org/t/p/w300/${item.poster_path}`} />
<h1 className="title"><a href="https">{item.name}</a></h1>
<p className="overview">{item.overview}</p>
</div>
)
})
return (
<TVShowsContext.Provider value={{ state, setState, fetchTVShows, handleSearchInput, suggestionSelected, renderSuggestedSearch, popularResultsRender }}>
{children}
</TVShowsContext.Provider>
);
}
import React,{ChangeEvent,useState,createContext,useContext,FC}来自'React';
从'react router dom'导入{Link};
从“axios”导入axios;
从“../../utils/api”导入{discoverTVShowsEndpoint,searchShowsEndpoint}
从“./SearchContext”导入{SearchContext};
类型InputElement=ChangeEvent
界面状态{
流行结果:[],
建议:[],
查询:字符串,
加载:布尔值
}
导出常量TVShowsContext=createContext(空)
导出常量TVShowsContextProvider:FC=({children})=>{
const{searchTerm,setSearchTerm}=useContext(SearchContext)
常量[状态,设置状态]=使用状态({
流行结果:[],
建议:[],
查询:searchTerm,
加载:false,
})
常量{popularResults,suggestions}=状态
常量handleSearchInput=(e:InputElement):void=>{
const query=e.target.value
setState((prevState:any)=>({…prevState,query}))//这确保onChange将触发
如果(query.length>0){
设置超时(()=>{
axios(`${searchShowsEndpoint}`+查询)
。然后({data})=>{
让结果=data.results