Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Window Resize - React + Redux

I'm new to Redux and I'm wondering if anyone has some tips on best practices for handling non React events like window resize. In my research, I found this link from the official React documentation: https://facebook.github.io/react/tips/dom-event-listeners.html

My questions is, when using Redux, should I store the window size in my Store or should I be keeping it in my individual component state?

like image 219
user2898229 Avatar asked Jan 28 '16 22:01

user2898229


People also ask

How do I change the window size in react?

To get the width and height of the window in React:Use the innerWidth and innerHeight properties on the window object. Add an event listener for the resize event in the useEffect hook. Keep changes to the width and height of the window in a state variable.

What happens when the window is resized?

The resize event fires when the document view (window) has been resized. This event is not cancelable and does not bubble. In some earlier browsers it was possible to register resize event handlers on any HTML element.

How do you're render the view when the browser is resized?

We can use the useLayoutEffect to add the event listener that runs when the window resizes. And in the window resize event handler, we can run our code to change a state to make the view rerender. We create the useWindowSize hook that has the size state.


1 Answers

Good question. I like to to have a ui part to my store. The reducer for which might look like this:

const initialState = {     screenWidth: typeof window === 'object' ? window.innerWidth : null };  function uiReducer(state = initialState, action) {     switch (action.type) {         case SCREEN_RESIZE:             return Object.assign({}, state, {                 screenWidth: action.screenWidth             });     }     return state; } 

The action for which is pretty boilerplate. (SCREEN_RESIZE being a constant string.)

function screenResize(width) {     return {         type: SCREEN_RESIZE,         screenWidth: width     }; } 

Finally you wire it together with an event listener. I would put the following code in the place where you initialise your store variable.

window.addEventListener('resize', () => {     store.dispatch(screenResize(window.innerWidth)); }); 

Media Queries

If your app takes a more binary view of screen size (e.g. large/small), you might prefer to use a media query instead. e.g.

const mediaQuery = window.matchMedia('(min-width: 650px)');  if (mediaQuery.matches) {     store.dispatch(setLargeScreen()); } else {     store.dispatch(setSmallScreen()); }  mediaQuery.addListener((mq) => {     if (mq.matches) {         store.dispatch(setLargeScreen());     } else {         store.dispatch(setSmallScreen());     } }); 

(I'll leave out the action and reducer code this time. It's fairly obvious what they look like.)

One drawback of this approach is that the store may be initialised with the wrong value, and we're relying on the media query to set the correct value after the store has been initialised. Short of shoving the media query into the reducer file itself, I don't know the best way around this. Feedback welcome.

UPDATE

Now that I think about it, you can probably get around this by doing something like the following. (But beware, I have not tested this.)

const mediaQuery = window.matchMedia('(min-width: 650px)');  const store = createStore(reducer, {     ui: {         largeScreen: mediaQuery.matches     } });  mediaQuery.addListener((mq) => {     if (mq.matches) {         store.dispatch(setLargeScreen());     } else {         store.dispatch(setSmallScreen());     } }); 

UPDATE II: The drawback of this last approach is that the ui object will replace the entire ui state not just the largeScreen field. Whatever else there is of the initial ui state gets lost.

like image 80
David L. Walsh Avatar answered Sep 21 '22 14:09

David L. Walsh