Crak_mboutin Crak_mboutin - 3 months ago 27
Javascript Question

React-intl disable react-router's Link component onClick event on Safari v8.0.8

I'm working on a react universal application who is rendered server side and client side. The application works #1 on Chrome, but on Safari, the react-router's

Link
just re-render the whole application and do an http request.

The application render correctly, but the links don't do the transitions in Safari when it work perfectly in Chrome.

This is my routing.js file who is an expressjs middleware

import React from 'react';
import { trigger } from 'redial';
import createMemoryHistory from 'history/lib/createMemoryHistory';
import useQueries from 'history/lib/useQueries';
import { match, RouterContext } from 'react-router';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

import { thunkMiddleware } from './thunkMiddleware';
import reducers from 'reducers';
import routes from '../routes';

const store = applyMiddleware(thunkMiddleware)(createStore)(reducers);
const { dispatch } = store;

function getRootComponent(renderProps) {
const state = store.getState();

const component = (
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
);

return {
component,
initialState: state,
};
}

function routing(req, res) {
const history = useQueries(createMemoryHistory)();
const location = history.createLocation(req.url);

return new Promise((resolve, reject) => {
match({ routes, location }, (error, redirectLocation, renderProps) => {
// Get array of route components:
const components = renderProps.routes.map(route => route.component);
// Define locals to be provided to all fetcher functions:
const locals = {
path: renderProps.location.pathname,
query: renderProps.location.query,
params: renderProps.params,
cookies: req.cookies,
// Allow fetcher functions to dispatch Redux actions:
dispatch,
};

if (typeof req.cookies.user_token === 'undefined' && (req.url !== '/login')) {
res.status(301).redirect('/login');
} else {
if (redirectLocation) {
reject(res.status(301).redirect(redirectLocation.pathname + redirectLocation.search));
} else if (error) {
reject(res.status(500).send(error.message));
} else if (renderProps === null) {
reject(res.status(404).send('Not found'));
}

// trigger l'action de "redial"
trigger('fetch', components, locals)
.then((cookieValues) => {
let cookieTime = 3600000; // 1 heure

if (typeof cookieValues !== 'undefined' && typeof cookieValues[0] !== 'undefined') {
if (typeof req.cookies.remember_me !== 'undefined') {
cookieTime = 1296000000; // 15 jours
res.cookie('remember_me', true, { maxAge: cookieTime, httpOnly: false });
}

res.cookie('user_loggedIn', cookieValues[0].user_loggedIn, { maxAge: cookieTime, httpOnly: false });
res.cookie('user_id', cookieValues[0].user_id, { maxAge: cookieTime, httpOnly: false });
res.cookie('user_token', cookieValues[0].user_token, { maxAge: cookieTime, httpOnly: false });
}

resolve(getRootComponent(renderProps));
})
.catch(reject);
}
});
});
}

export default routing;


And this is my
app.js
for my client side rendering

history.listen(() => {
// Match routes based on location object:
match({ history, routes }, (routerError, redirectLocation, renderProps) => {
console.log(routerError, redirectLocation, renderProps);
// Check si renderProps est true sinon c'est un redirect
if (renderProps) {
// Get array of route components:
const components = renderProps.routes.map(route => route.component);

// Define locals to be provided to all lifecycle hooks:
const locals = {
path: renderProps.location.pathname,
query: renderProps.location.query,
params: renderProps.params,
state: store.getState(),
// Allow lifecycle hooks to dispatch Redux actions:
dispatch,
};

// Fetch deferred, client-only data dependencies
trigger('defer', components, locals)
// Finally, trigger 'done' lifecycle hooks:
.then(() => {
const state = store.getState();

// checkIfFormIsCompleted(location, state, () => {
renderApplication();

trigger('done', components, { ...locals, state });
// });
});
}

function renderApplication() {
ReactDOM.render((
<Provider store={store}>
<Router history={history}>{routes}</Router>
</Provider>
), document.getElementById(APP_DOM_CONTAINER));
}
});
});


When i
console.log
all in both, and all was ok. No errors, nothing wrong on the server and the client side. The links just don't want to trigger the history changes and do the application changes.

I use react-router-redux too if it matter and i just updated the packages just to check if they'll work, but nothing changes.

"react": "^15.1.0",
"react-router": "^2.7.0",
"react-router-redux": "^4.0.0",
"redux": "^3.0.6",
"redux-form": "^5.2.4",


I just digged into the DOM to see how click events are binds and i saw that links in Safari misses the event from
ReactEventListener.js
.

http://imgur.com/a/GA7bI

Thank you for your help!

Answer

Hi had to add this polyfill script to my HTML page.

<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.fr,Intl.~locale.en" />

After, all works well! There was no console error or anything on my work's iMac, but on my laptop, an error was on the console.

You can see more infos here:

http://formatjs.io/github/#polyfills

Comments