有一个目录组件,一些redux存储;react 上下文提供程序代码.在路由v6之前,他们包装了一个包含目录子路由的嵌套<BrowserRouter>
,如下所示
之前
client/src/components/Catalogue/index.js
import React, { useCallback, useEffect, useState } from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";
import { Provider, connect } from "react-redux";
import { createStore, combineReducers } from "redux";
import { getPeopleBy, getChaptersBy, getPostsBy } from "../../api"
import playlistReducer from "../../store/reducers/playlists";
import SideBar from "../CatalogueSidebar/SideBar";
import CatalogueHeader from "../CatalogueHeader/CatalogueHeader"
import CatalogueHome from "../CatalogueHome/CatalogueHome";
import CatalogueSearch from "../CatalogueSearch";
import People from "../People/People";
import Chapters from "../Chapters/Chapters";
import Posts from "../Posts/Posts";
import PostDetail from "../PostDetail/PostDetail";
import FooterBar from "../FooterBar/FooterBar";
import style from "./Catalogue.module.css"
const Catalogue = () => {
const [chapters, setChapters] = useState(null)
const [people, setPeople] = useState(null)
const [posts, setPosts] = useState(null)
const fetchCatalogue = async () => {
let chapters = await getChaptersBy("latest")
let people = await getPeopleBy("active")
let posts = await getPostsBy("recently_added")
return { chapters, people, posts }
}
useEffect(() => {
document.documentElement.className = ""; //<head>
document.body.className = style.CatalogueBody; //<body>
fetchCatalogue().then(response => {
setChapters(response.chapters)
setPeople(response.people)
setPosts(response.posts)
})
return () => {
setChapters(null)
setPeople(null)
setPosts(null)
}
}, [])
const reducers = combineReducers({
chapters: playlistReducer,
people: playlistReducer,
});
const store = createStore(reducers);
return (
<Provider store={store}>
<div className={style.App}>
<Router>
<SideBar />
<CatalogueHeader account={{display_name: "User"}}/>
<Route path="/catalogue" exact>
<CatalogueHome chapters={chapters} people={people} posts={posts}/>
</Route>
<Route path="/catalogue/search">
<CatalogueSearch />
</Route>
<Route path="/catalogue/posts">
<Posts/>
</Route>
<Route path="/catalogue/posts/:id">
<PostDetail />
</Route>
<Route path="/catalogue/people">
<People />
</Route>
<Route path="/catalogue/chapters">
<Chapters />
</Route>
</Router>
<FooterBar />
</div>
</Provider>
);
};
const mapStateToProps = (state) => {
return {
posts: state.posts,
people: state.people,
};
};
const mapDispatchToProps = (dispatch) => {
return {
initPosts: (data) => dispatch({ type: "init", posts: data }),
initPeople: (data) => dispatch({ type: "init", people: data }),
};
};
export default Catalogue;
client/src/components/App.js
import React, { useState } from "react";
import { Route, Switch, BrowserRouter } from "react-router-dom";
import TierA from "./TierA"
import TierB from "./TierB"
import Catalogue from "./Catalogue"
import Admin from "./Admin"
import NotFound from "./NotFound"
import PlayerContext from "./Player/context"
import SearchContext from "./Search/context"
import CatalogueSearchContext from "./CatalogueSearch/context"
import { useSearch } from "../hooks/useSearch"
const App = () => {
const searchText = useSearch()
const [playerItem, setPlayerItem] = useState(null)
return (
<React.Fragment>
<SearchContext.Provider value={searchText}>
<CatalogueSearchContext.Provider value={searchText}>
<PlayerContext.Provider value={{ playerItem, setPlayerItem }}>
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Switch>
<Route component={TierA} exact path="/tier_a" />
<Route component={TierB} exact path="/tier_b" />
<Route component={Catalogue} path="/catalogue" />
<Route component={Admin} path="/admin" />
<Route component={NotFound} />
</Switch>
</BrowserRouter>
</PlayerContext.Provider>
</CatalogueSearchContext.Provider>
</SearchContext.Provider>
</React.Fragment>
)
}
export default Routes;
之后
更新"react-router-dom": "^5.1.2"
到"react-router-dom": "^6.3.0"
,目录路由有一些问题.将Catalogue
个子组件移动到App
,但仅保留CatalogueHome
个,将为目录索引"/"
呈现
client/src/components/Catalogue/index.js
import React, { useCallback, useEffect, useState } from 'react';
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { Provider, connect } from "react-redux";
import { createStore, combineReducers } from "redux";
import { getPeopleBy, getChaptersBy, getPostsBy } from "../../api"
import playlistReducer from "../../store/reducers/playlists";
import playingReducer from "../../store/reducers/playing";
import SideBar from "../CatalogueSidebar/SideBar";
import CatalogueHeader from "../CatalogueHeader/CatalogueHeader"
import CatalogueHome from "../CatalogueHome/CatalogueHome";
import CatalogueSearch from "../CatalogueSearch";
import Posts from "../Posts/Posts";
import PostDetail from "../PostDetail/PostDetail";
import People from "../People/People";
import Chapters from "../Chapters/Chapters";
import FooterBar from "../FooterBar/FooterBar";
import style from "./Catalogue.module.css"
const Catalogue = () => {
const [chapters, setChapters] = useState(null)
const [people, setPeople] = useState(null)
const [posts, setPosts] = useState(null)
const fetchCatalogue = async () => {
let chapters = await getChaptersBy("latest")
let people = await getPeopleBy("active")
let posts = await getPostsBy("recently_added")
return { chapters, people, posts }
}
useEffect(() => {
document.documentElement.className = ""; //<head>
document.body.className = style.CatalogueBody; //<body>
fetchCatalogue().then(response => {
setChapters(response.chapters)
setPeople(response.people)
setPosts(response.posts)
})
return () => {
setChapters(null)
setPeople(null)
setPosts(null)
}
}, [])
const reducers = combineReducers({
chapters: playlistReducer,
people: playlistReducer,
});
const store = createStore(reducers);
return (
<Provider store={store}>
<div className={style.App}>
<SideBar />
<CatalogueHeader account={{display_name: "User"}}/>
<CatalogueHome chapters={chapters} people={people} posts={posts}/>
<FooterBar />
</div>
</Provider>
);
};
const mapStateToProps = (state) => {
return {
posts: state.posts,
people: state.people,
};
};
const mapDispatchToProps = (dispatch) => {
return {
initPosts: (data) => dispatch({ type: "init", posts: data }),
initPeople: (data) => dispatch({ type: "init", people: data }),
};
};
export default Catalogue;
新应用程序.js没有"catalogue"
的绝对路径,因此它使用react router v6和<Outlet/>
,但它缺少所有redux和;需要引用的上下文包装器:
import React, { useState } from "react";
import { BrowserRouter, Route, Routes, Outlet } from "react-router-dom";
import TierA from "./TierA"
import TierB from "./TierB"
import Catalogue from "./Catalogue"
import CatalogueHome from "./CatalogueHome/CatalogueHome";
import CatalogueSearch from "./CatalogueSearch";
import Chapters from "./Chapters/Chapters";
import PostDetail from "./PostDetail/PostDetail";
import People from "./People/People";
import Posts from "./Posts/Posts";
import Admin from "./Admin"
import NotFound from "./NotFound"
import PlayerContext from "./Player/context"
import SearchContext from "./Search/context"
import CatalogueSearchContext from "./CatalogueSearch/context"
import { useSearch } from "../hooks/useSearch"
const App = () => {
const searchText = useSearch()
const [playerItem, setPlayerItem] = useState(null)
return (
<React.Fragment>
<SearchContext.Provider value={searchText}>
<CatalogueSearchContext.Provider value={searchText}>
<PlayerContext.Provider value={{ playerItem, setPlayerItem }}>
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Routes>
<Route path="/tier_a" element={<TierA/>}/>
<Route path="/tier_b" element={<TierB/>}/>
<Route path="catalogue">
<Route index element={<Catalogue/>}/>
<Route path="search" element={<CatalogueSearch />}/>
<Route path="posts" element={<Post/>}/>
<Route path="post/:id" element={<PostDetail />}/>
<Route path="people" element={<People />}/>
<Route path="chapters" element={<Chapters />}/>
</Route>
<Route path="/admin" element={<Admin/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</BrowserRouter>
</PlayerContext.Provider>
</CatalogueSearchContext.Provider>
</SearchContext.Provider>
</React.Fragment>
)
}
export default App;
try 点击任何目录嵌套路由(如/catalogue/posts
或/catalogue/people
)时,出现以下错误:
Uncaught Error: Could not find "store" in the context of "Connect(PostDetail)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(PostDetail) in connect options.
at ConnectFunction (connect.js:244:1)
at renderWithHooks (react-dom.development.js:16175:1)
at updateFunctionComponent (react-dom.development.js:20387:1)
at updateSimpleMemoComponent (react-dom.development.js:20222:1)
at updateMemoComponent (react-dom.development.js:20081:1)
at beginWork (react-dom.development.js:22502:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4161:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4210:1)
at invokeGuardedCallback (react-dom.development.js:4274:1)
at beginWork$1 (react-dom.development.js:27405:1)
我的问题是,我是否需要将Catalogue
个代码(如useEffect()
、states、contextProviders)移动到App.js
才能让props 工作?"store"
和;etc适用于每个目录子项.由于错误,我无法将提供程序代码放入<Routes> </Routes>
Error: [Provider] is not a <route> component. all component children of <routes> must be a <route> or <react.fragment>
请告知如何修复.提前感谢