Как использовать React Router с Preact
Я использую Preact в качестве каркаса просмотра (НЕ могу использовать React из-за проблем с IP-адресом Facebook). Мне нужно было использовать React Router для маршрутизации местоположения, потому что он обладает большей гибкостью, чем Preact Router, созданный той же командой.
Мне удалось заставить React Router принимать Preact вместо React, однако я не могу заставить его соответствовать местам. Я не уверен, что это проблема совместимости или проблема конфигурации. Я попытался использовать только одну пару маршрутов (приложение и учетная запись), и он все еще не работает с этой упрощенной настройкой.
Q: Кто-нибудь видит, делаю ли я здесь что-то не так?
Я получаю ошибку: 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;
};
4 ответа
(ОП уже решил свою проблему, но это высоко ценится в Google и не очень полезно для новичков, поэтому я подумал, что предоставлю некоторую справочную информацию)
Preact и Preact-Compat
preact - это минимальная версия React, которая весит всего 3Kb. Он реализует подмножество API React с некоторыми небольшими отличиями здесь и там. Он также поставляется с вспомогательной библиотекой preact-compat, которая обеспечивает совместимость с React, заполняя недостающие части и исправляя различия API.
Реагировать-маршрутизатор
response-router - это библиотека маршрутизаторов, предназначенная для работы с React. Но вы также можете заставить его работать с Preact, используя preact-compat
,
Настройка preact-compat
npm i --save preact-compat
Убедитесь, что вы создали псевдонимы для react
а также react-dom
в вашей конфигурации webpack / browserify или напишите некоторый код, чтобы настроить эти псевдонимы вручную.
пример конфигурации веб-пакета
{
// ...
resolve: {
alias: {
'react': 'preact-compat',
'react-dom': 'preact-compat'
}
}
// ...
}
Затем вы можете использовать компоненты React как есть. Они не будут знать, что они отображаются в Preact iso React. Посмотрите на этот пример preact-compat.
Проблемы с совместимостью
Имейте в виду, что когда вы используете Preact Compat, вы рискуете. Джейсон - очень умный парень, но его библиотека составляет лишь небольшую часть от той, что предоставлена Facebook, поэтому есть некоторые различия. Компоненты, которые используют менее известные функции React, могут работать неправильно. Если вы столкнулись с такими проблемами, сообщите о них в систему отслеживания проблем preact-compat (с минимальным воспроизведением в форме репозитория GitHub), чтобы помочь ему улучшить ее.
В прошлом было несколько таких проблем, которые мешали React-Router корректно работать с Preact, но с тех пор они были исправлены, и теперь вы сможете использовать их вместе.
Скрипка Преакта + Реакт-Роутер
Взгляните на эту JS Fiddle для рабочего примера.
Обновленный ответ: есть пакет 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);
Вот расширенное решение для 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);
Нашел проблему, была пара проблем с совместимостью Preact с React:
Контексты не обрабатываются правильно:
https://github.com/developit/preact/issues/156
props.children
неправильно обработано: