如何将 React 路由器与 Preact 一起使用
Posted
技术标签:
【中文标题】如何将 React 路由器与 Preact 一起使用【英文标题】:How to use React Router with Preact 【发布时间】:2016-09-15 07:53:33 【问题描述】:我正在使用 Preact 作为我的视图框架(由于 Facebook IP 问题,可以不使用 React)。我需要使用 React Router 进行位置路由,因为它比同一个团队构建的 Preact Router 具有更大的灵活性。
我设法让 React Router 接受 Preact 代替 React,但是,我无法让它匹配位置。我不确定这是兼容性问题还是配置问题。我已尝试仅使用一对路由( App 和 Account ),但它仍然不适用于简化的设置。
问:有没有人看到我在这里做错了什么?
我得到的错误是:Location "/account/12345/" did not match any routes
main.js
import h, render from 'preact';
import Router, browserHistory from 'react-router';
import Provider from 'react-redux';
import createStore from './createStore';
import createRoutes from './createRoutes';
process.env.DEBUG && console.log('Hello, developer!');
const history = browserHistory;
const store = createStore( history );
const routes = createRoutes( store );
render((
<Provider store= store key="redux-provider">
<Router history= history createElement= h routes= routes />
</Provider>
), document.body );
createRoutes.js
import h from 'preact';
import IndexRoute, Route from 'react-router';
// App Component
import App from './components/app';
// Sub Components
import Account from './components/account';
import Conversation from './components/conversation';
import Dashboard from './components/dashboard';
// Error Components
import BadAccount from './components/bad-account';
import NotFound from './components/not-found';
// Routes
export default ()=> (
<Route path="/" component=App>
/* Get URL parameter */
<Route path="account/:accountID" component=Account>
/* Index Route */
<IndexRoute component=Dashboard />
/* Sub Routes ( Alphabetical Please ) */
<Route path="chat" component=Conversation />
/* Catch-All Route */
<Route path="*" component=NotFound />
</Route>
/* Handle Invalid URIs */
<Route path="*" component=BadAccount />
</Route>
);
createStore.js
import applyMiddleware, combineReducers, compose, createStore from 'redux';
import thunk from 'redux-thunk';
import routerMiddleware from 'react-router-redux';
import messages from './resources/messages/reducer';
import conversation from './resources/conversation/reducer';
import layout from './resources/layout/reducer';
import profile from './resources/profile/reducer';
import contract from './resources/contract/reducer';
/*const devToolsExtension = window;*/
export default history =>
// Sync dispatched route actions to the history
const reduxRouterMiddleware = routerMiddleware( history );
// Create single reducer from all modules
const rootReducer = combineReducers(
messages,
conversation,
layout,
profile,
contract
);
// List redux middleware to inject
const middleware = [
thunk,
reduxRouterMiddleware
];
// Compose the createStore function
const createComposedStore = compose(
applyMiddleware( ...middleware )/*, // Figure this out...
( process.env.DEBUG && devToolsExtension ) ? devToolsExtension() : f => f*/
)( createStore );
// Create the store
const store = createComposedStore( rootReducer );
// Hook up Redux Routing middleware
// reduxRouterMiddleware.listenForReplays(store);
// Return store
return store;
;
【问题讨论】:
请注意,从 react-router v4 开始,Preact 支持开箱即用。如果您在将 react-router v4 与 Preact 结合使用时遇到问题,则解决方案可能不在这里 【参考方案1】:(OP 已经解决了他的问题,但这在 Google 中排名很高,对新手帮助不大,所以我想我会提供一些背景信息)
Preact 和 preact-compat
preact 是 React 的最小版本,只有 3Kb。它实现了 React API 的一个子集,这里和那里有一些小的差异。它还附带一个帮助程序库 preact-compat,它通过填充缺失的部分和修补 API 差异来提供与 React 的兼容性。
反应路由器
react-router 是一个路由器库,旨在与 React 一起使用。但是您也可以使用 preact-compat
使其与 Preact 一起使用。
设置 preact-compat
npm i --save preact-compat
确保在 webpack / browserify 配置中为 react
和 react-dom
设置别名,或者编写一些代码手动设置这些别名。
示例 webpack 配置
// ...
resolve:
alias:
'react': 'preact-compat',
'react-dom': 'preact-compat'
// ...
然后您可以按原样使用 React 组件。他们不会知道他们正在被 Preact i.s.o. 渲染。做出反应。看看这个preact-compat-example。
兼容性问题
请记住,当您使用 Preact Compat 时,您是在冒险。 Jason 是一个非常聪明的人,但他的库只有 Facebook 提供的库的一小部分,所以肯定会有一些差异。使用 React 鲜为人知的功能的组件可能无法正常工作。如果您遇到此类问题,请将其报告给preact-compat issue tracker(以 GitHub 存储库的形式进行最少的复制)以帮助他改进。
过去有一些这样的问题会阻止 React-Router 与 Preact 一起正常工作,但这些问题已经得到修复,您现在应该能够很好地结合使用这两者。
Preact + React-Router 的小提琴
查看this JS Fiddle 的工作示例。
【讨论】:
【参考方案2】:更新的答案是现在有一个 preact-router 包:https://www.npmjs.com/package/preact-router
import Router from 'preact-router';
import h from 'preact';
const Main = () => (
<Router>
<Home path="/" />
<About path="/about" />
<Search path="/search/:query" />
</Router>
);
render(<Main />, document.body);
【讨论】:
如果需要,您实际上可以将原始 React Router 与 Preact 一起使用。请注意,OP 提到他“需要使用 React Router 进行位置路由,因为它比 Preact Router [..] 具有更大的灵活性” 嘿,我如何使用它从 url 中获取多个可选参数--------------- : /about/user?id=5&name=abc【参考方案3】:发现问题,是 Preact 与 React 兼容性的一对问题:
上下文未正确处理:
https://github.com/developit/preact/issues/156
props.children
处理不正确:
https://github.com/developit/preact-compat/issues/47#issuecomment-220128365
【讨论】:
【参考方案4】:这是具有哈希支持的 preact-router 的扩展解决方案。 适用于重新加载和直接访问。
https://www.webpackbin.com/bins/-KvgdLnM5ZoFXJ7d3hWi
import Router, Link from 'preact-router';
import h, render from 'preact';
import createHashHistory from 'history';
[cut]...[/cut]
const App = () => (
<div>
<Header />
<Router history=createHashHistory()>
<Page1 default path="/" />
<Page2 path="/page2" />
</Router>
</div>
);
render(<App />, document.body);
【讨论】:
以上是关于如何将 React 路由器与 Preact 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
如何将 create-react-app 转换为 Preact?
如何将 React.createContext() 与反应路由器一起使用?
如何将 React Context API 与 useReducer 一起使用以遵循与 Redux 类似的风格 [关闭]