symfony-react-sandbox icon indicating copy to clipboard operation
symfony-react-sandbox copied to clipboard

Integration with FOSJsRoutingBundle

Open nacmartin opened this issue 8 years ago • 7 comments

RIght now the routes in React are hardcoded, and that is ugly. We should be able to use FosJsRoutingBundle and integrate it into Webpack.

I guess we could require in the Webpack bundles web/bundles/fosjsrouting/js/router.js and also load the route fos_js_routing_js with a url-loader.

nacmartin avatar Feb 23 '16 11:02 nacmartin

Did anyon succesfully combine the 2 yet?

jrmyio avatar Oct 25 '16 23:10 jrmyio

Is this still in the works? Would be much easier to work with

tma11ey avatar Feb 07 '17 15:02 tma11ey

If someone has a good idea/implementation for this...

nacmartin avatar Feb 08 '17 10:02 nacmartin

I do it like this: in webpack.config.babel.js


const setup = {
  resolve: {
    alias: {
       'FosRouter': path.resolve('./web/bundles/fosjsrouting/js/', 'router.js'),
       'FosRoutes': path.resolve('./web/js/', 'fos_js_routes.js')
     },
     modules: [
       path.resolve('js'),
       'node_modules'
     ]
   }
 module.exports = setup;

then in react - create a component:

import 'FosRouter';
import 'FosRoutes';

const Router = window.fos && window.fos.Router;

export default Router.getInstance();

and then import this component where u need the get the route:

import Router from '../util/Router';

console.log(Router.generate('app_options'));

luchianenco avatar Apr 07 '17 07:04 luchianenco

@luchianenco how do you get window working in SSR ? i'm using a dynamic route handling, you can saw an little exemple in react-router doc https://reacttraining.com/react-router/web/guides/server-rendering/data-loading using a array of route object sending from symfony, this array is actualy writed by hand but i'll make a manager to dynamicaly add a route from any bundle by using service (actually in syfmony 3.x we can easily call service by require them with a type requirement argument ...)

i'm using 'switchs' in my routes array to configure imbriqued routes but you can name whatever you want

here is my actual array sending

'router' => [
                                'routes' =>[
                                        [
                                        'name' => 'admin',
                                        'path' => '/:locale/admin',
                                        'exact' => false,
                                        'show' => false,
                                        'component' => 'AdminNavbar',
                                        'switchs' => [
                                            [
                                                'name' => 'adminRoot',
                                                'path' => '/:locale/admin',
                                                'exact' => true,
                                                'component' => 'AdminRoot',
                                                'switchs' => []
                                            ],
                                            [
                                                'name' => 'adminNotFoud',
                                                'path' => '/:locale/admin/*',
                                                'exact' => false,
                                                'component' => 'NotFound',
                                                'switchs' => []
                                            ]
                                        ],
                                        'links' => [
                                            [
                                                'type' => 'internal',
                                                'path' => '/:locale/',
                                                'name' => 'homepage',
                                                
                                            ]
                                        ],
                                            
                                        ],
                                        [
                                        'name' => 'homepage',
                                        'path' => '/:locale/',
                                        'exact' => false,
                                        'show' => false,
                                        'component' => 'MainNavbar',
                                        'switchs' => [
                                                [
                                                    'name' => 'root',
                                                    'path' => '/:locale/',
                                                    'exact' => true,
                                                    'component' => 'MainRoot',
                                                    'switchs' => []
                                                ],
                                                [
                                                    'name' => 'main',
                                                    'path' => '/:locale/main',
                                                    'exact' => false,
                                                    'component' => 'Main',
                                                    'switchs' => [
                                                        [
                                                            'name' => 'mainTimer',
                                                            'path' => '/:locale/main/timer',
                                                            'exact' => false,
                                                            'component' => 'Timer',
                                                            'switchs' => [
                                                                [
                                                                    'name' => 'mainTimerTimer',
                                                                    'path' => '/:locale/main/timer/timer',
                                                                    'exact' => false,
                                                                    'component' => 'Timer', 
                                                                    'switchs' => []
                                                                ]
                                                                
                                                            ]
                                                        ],
                                                    ]
                                                ],
                                                [
                                                    'name' => 'timer',
                                                    'path' => '/:locale/timer',
                                                    'exact' => false,
                                                    'component' => 'Timer',
                                                    'switchs' => [],
                                                ],
                                                [
                                                    'name' => 'notFound',
                                                    'path' => '/:locale/*',
                                                    'exact' => false,
                                                    'component' => 'NotFound',
                                                    'switchs' => []
                                                ]
                                            ],
                                            'links' => [
                                                [
                                                'type' => 'internal',
                                                'path' => '/:locale/admin',
                                                'name' => 'admin',
                                                'switchs' => [
                                                    [
                                                    'name' => 'testtest',
                                                    'path' => '/:locale/testtest', 
                                                    ]
                                                ]
                                                ],
                                                
                                            ],
                                        ],
                                        
                                        
                                ],
                                ]

this is added to a global store to let every components acces this array if necessary and there is my route component who generate the tree to be used by react router

import React from 'react'
import  App  from '../container/App'
import  * as AllComponent from '../container/index'
import { connect } from 'react-redux'
import {
      Route,
      Switch,
      withRouter
} from 'react-router-dom'

class Routes extends React.Component {
        
    constructor(props){
        super(props)
        
    }
    
    addRoute(r,i){
        const Component = AllComponent[r.component]
        if( typeof(Component) === 'undefined'){
            if(this.props.env.devMode === true){
                console.log("'" + r.component + '\' component not found ! from ' , r)   
            }
            return false
        }
        return(
            <Component exact={r.exact} key={i} path={r.path}  >
                <Switch> 
                    { r.switchs.map(this.addRoute.bind(this))}
                </Switch>
            </Component>
        )
    }
    
    
    render() {
        return (
                <App>
                    <Switch>
                       {
                        this.props.router.routes.map(this.addRoute.bind(this))
                       }
                    </Switch>
                </App>
        );
    }
}


const mapStateToProps = (state) => (
    {
       localeManager: state.localeManager,
       request: state.request,
       router: state.router,
       env: state.env
    }
)

export default withRouter(connect(mapStateToProps)(Routes))


the AllComponent is an object who let call any component with a string name (stored with route) i also added link who isnt used in route component but usefull to set up additional link for dynamic render a navbar (for exemple a link to admin from home and a link to home from admin), is up to you to add aditional info to set admin role requirement for route show or seomething else in router....

//  .../container/index.js

export { default as AdminNavbar } from './AdminNavbar'
export { default as AdminRoot } from './AdminRoot'
export { default as App } from './App'
export { default as Main } from './Main'
export { default as MainNavbar } from './MainNavbar'
export { default as MainRoot } from './MainRoot'
export { default as NotFound } from './NotFound'
export { default as Timer } from './timer'

grimpows avatar Aug 12 '17 12:08 grimpows

@luchianenco here is an alternative solution from @weaverryan

https://github.com/symfony/webpack-encore/issues/97#issuecomment-315757285

acidjames avatar Nov 06 '17 09:11 acidjames

@acidjames this is a nice tool, but in April it was not yet published ;)

luchianenco avatar Nov 06 '17 09:11 luchianenco