Issues getting React Router to work in Symfony 6 - javascript

I seem to be having issues getting react-router working within a Symfony 6 installation inside a sub-directory.
The react router keeps throwing a 404 error for all routes:
> Object { status: 404, statusText: "Not Found", internal: true, data:
> "Error: No route matches URL \"/work/ls/public/\"", error: Error }
> app.0e8e7ca1.js:1:507
I have installed Symfony, WebPackEncoreBundle and created a ReactController and Twig template:
<?php
// src/Controller/ReactController.php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
class ReactController extends AbstractController
{
public function number(): Response
{
return $this->render('react/index.html.twig');
}
}
The YAML route file is as follows:
react_controller:
path: /{reactRouting}
controller: App\Controller\ReactController::number
defaults: { reactRouting: null }
Within webpack.config.js I have the following settings:
// enable react present
.enableReactPreset()
// directory where compiled assets will be stored
.setOutputPath('public/build')
// public path used by the web server to access the output path
.setPublicPath('/work/ls/public/build')
I've also tried adding "homepage" to package.json:
"homepage": "http://localhost/work/ls"
React code below:
import React from 'react';
import ReactDOM from 'react-dom/client';
import Dashboard from './components/Dashboard';
import Login from './components/Login';
import ErrorPage from './components/ErrorPage';
// Import router
import { createBrowserRouter, RouterProvider, useLocation } from 'react-router-dom';
const router = createBrowserRouter([
{
path: "/",
element: <Dashboard />,
errorElement: <ErrorPage />
},
{
path: "/login",
element: <Login />
}
]);
const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>
);
When creating a new React project separately from Symfony at the root directory, using the same code, the routing works as expected.
Can anyone see where I am going wrong?

Related

Why is react i18next not working ? no errors

The translations do not work I only see the keys. Instead of having "Welcome to MySite" I only have "welcome.title MySite".
my i18nextConf.js file
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
const fallbackLng = ['fr'];
const availableLanguages = ['en','fr'];
i18n
.use(Backend) // load translations using http (default public/assets/locals/en/translations)
.use(LanguageDetector) // detect user language
.use(initReactI18next) // pass the i18n instance to react-i18next.
.init({
fallbackLng, // fallback language is english.
backend: {
/* translation file path */
// loadPath: './translations/{{lng}}/{{ns}}.json'
loadPath: './translations/{{lng}}/common.json'
},
detection: {
checkWhitelist: true, // options for language detection
},
debug: false,
whitelist: availableLanguages,
interpolation: {
escapeValue: false, // no need for react. it escapes by default
},
});
export default i18n;
My index.js file
import React,{ Suspense } from 'react';
import './i18nextConf';
// code omitted
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<Suspense fallback={null}>
<App />
</Suspense>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
My translations files in src/translations/en/common.json and src/translations/fr/common.json
{
"welcome": {
"title": "Welcome to "
}
}
my CustomComponent.js
import React,{ Component } from 'react';
import { withTranslation } from "react-i18next";
class CustomComponent extends Component {
render() {
const { t } = this.props;
return (
<div className="section-title">
<h2 className={classes.myTitle}>{t('welcome.title')}</h2>
</div>
);
}
}
export default withTranslation()(CustomComponent);
Is there something wrong with my configuration ? What do I have to change ?
Those translation files will be served from the base path from where your index.html is also loaded and in-case it's an app created using create-react-app, that folder is public.
So I think when you are saying in loadPath that load files from ./translations/{{lng}}/common.json, the request actually gets resolved to public/translation/en/common.json but your files are located at src..... as you stated.
You can try either moving those files inside public (check this example for reference also ) or you can try the other syntax where you explicitly import the json from each file (inside src) and add it to a resources object which you pass to configuration as shown here

Heroku is giving me 404 error, only renders "Unkown path"?

I'm trying to deploy my application to heroku, however when I try to open the link to it, the only thing being rendered is "unkown path", erros being "Failed to load resource: the server responded with a status of 404 (Not Found)".
I kept checking the routes files as much as I could and I can't see what doesn't work here. This is how the index.js file looks like
import route from './router.js';
import Login from '../ui/pages/user/Login';
import Home from '../ui/Home';
import Register from '../ui/pages/user/Register';
import PostCreate from '../ui/pages/post/PostCreate';
import PostList from '../ui/pages/post/PostList';
import PostEdit from '../ui/pages/post/PostEdit';
route('/', Home, {}, {
name: 'home'
});
route('/login', Login, {}, {
name: 'login'
});
route('/register', Register, {}, {
name: 'register'
});
route('/post/create', PostCreate, {}, {
name: 'post.create'
});
route('/post/list', PostList, {}, {
name: 'post.list'
});
route('/post/edit/:_id', PostEdit, {}, {
name:'post.edit'
});
And this is the router.js file
import { createRouter } from 'meteor/cultofcoders:meteor-react-routing';
import App from '/imports/ui/App.jsx';
export default createRouter(App);
Could it just be an issue regarding the routing package I'm using?
I feel you are using the "wrong" router. cultofcoders:meteor-react-routing seems to not have been maintained in the past 2 years which is huge in terms of react routing. Would you be interested to try "react-router": "^5.0.0" with "react-router-dom": "^5.0.0" then you have something like:
import React from 'react'
import { Switch, Route, Redirect } from 'react-router-dom'
import Component1 from '.....'
import Component2 from '.....'
const Main = location => {
return (
<Switch location={location.location}>
<Route exact path='/' component={Component1} />
<Route exact path='/something' component={Component2} />
<Route exact path='/something/:id' component={Component2} /> // route with param
<Route path='*' component={NotFoundPage} />
...........
</Switch>)
}

Module js import/export issue (vue.js)

I'm trying to teach SPA in Laravel + Vue.
I have a few pretty simpe components.
<template>
<p>Home</p>
</template>
<script>
export default {
name: 'Home'
}
</script>
Also, I have a router file
import Home from '../pages/home.vue';
import Profile from '../pages/profile.vue';
export let routes = [
{
path : '/home',
component : Home
},
{
path : '/profile',
component : Profile
}
];
npm run dev - "build successfull"
I've attached router-link tags and placed router-view.
But there is just . It's gives the same result with "out of the box" Laravel example-component.vue .
It seems there is somethng wrong with import settings in my component, but what?
The problem was in the project structure.
I have a router/routes.js and app.js file
In app.js I import routes from routes.js and do new VueRouter.
The error was:
import {routes} from './router/routes';
let router = new VueRouter(routes);
Should be
import {routes} from './router/routes';
let router = new VueRouter({routes});

React Router Authentication Async

I'm new to react.
I want to add some security to my Async-Routes which I implemented in my routes.js:
import React from 'react';
import App from './app.jsx';
import Home from './components/home.jsx';
import {Router, Route, IndexRoute, hashHistory} from 'react-router';
function loadRoute(cb) {
return (module) => cb(null, module.default);
}
const routes = {
component: App,
childRoutes: [
{
path: "/",
component: Home
},
{
path: "/hello/:foo",
getComponent(location, cb) {
System.import('./components/hello.jsx')
.then(loadRoute(cb))
.catch(errorLoading);
}
},
]
};
export default () => <Router history={hashHistory} routes={routes} />
As you can see the "/hello/:foo" route is async.
How can I restrict the access to this route (role-based) and redirect to somewhere else (e.g. login)?
I want to load the chunk only when it's needed.
Should I place the checking code into "getComponent()"?
Can it be done with "willTransitionTo()", will this function be executed before "getComponent()" and how should I implement it?
I would place the checking code into componentWillMount(), and in render() return the page component, or display/redirect to login.
If you have multiple page that need access restricted, I'd create a high level component order for each page component to check access before rendering.

React Hot Reloader 3

I'm trying the new React Hot Loader 3 and I'm receiving an warning message:
warning.js:44 Warning: React.createElement: type should not be null,
undefined, boolean, or number. It should be a string (for DOM
elements) or a ReactClass (for composite components). Check the render
method of AppContainer.
This is the App file. What is wrong?
Ps: It's written the same way as on examples.
Ps2: The problem is not in the App since it renders on the render() outside the if statement
Ps3: The warning only appears when the browser tries to 'hot-reload' (when I make changes to any file)
import React from 'react';
import { render } from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import a11y from 'react-a11y'
import Store from './stores/Store';
import App from './components/App/App';
const store = new Store();
if(process.env.NODE_ENV === 'development'){
a11y(React);
}
render(
<AppContainer
component={App}
props={{ store }}
/>,
document.getElementById('root')
);
if (module.hot) {
module.hot.accept('./components/App/App', () => {
render(
<AppContainer
component={require('./components/App/App').default}
props={{ store }}
/>,
document.getElementById('root')
);
});
}
Ok, the problem was with my .babelrc file. I had some other plugins, that I've removed, and it worked:
{
"presets": ["es2015-loose", "react", "stage-1"],
"plugins": [
"react-hot-loader/babel",
"transform-decorators-legacy"
],
}

Categories