Search code examples
javascriptreactjsreduxredux-thunk

react - redux - thunk changing background of the page the concise way


I'm trying to have my page change background color, so that the initialisation page has a different background.

My LogoPage component:

import PropTypes from "prop-types";
import React from "react";

import ReactOnRails from "react-on-rails";
import LocationContainer from "../containers/LocationContainer";

const LogoPage = () => {
  return (
    <div className="logoPage">
      <h1>Name</h1>
      <LocationContainer />
    </div>
  );
};

LogoPage.propTypes = {};

export default LogoPage;

This is shown when the app is trying to fetch the users gps location called by the landingPage component:

import PropTypes from "prop-types";
import React from "react";

import ReactOnRails from "react-on-rails";
import NikelesContainer from "../containers/NikelesContainer";
import LogoPageContainer from "../containers/LogoPageContainer";

const Landing = props => {
  if (props.latitude && props.longitude) {
    return (
      <div className="body">
        <NikelesContainer />
      </div>
    );
  } else {
    return (
      <div className="body">
        <LogoPageContainer />
      </div>
    );
  }
};

Landing.propTypes = {
  latitude: PropTypes.number,
  longitude: PropTypes.number
};

export default Landing;

The LogoPageContainer:

import { connectWithLifecycle } from "react-lifecycle-component";

import LogoPage from "../components/LogoPage";
import setRedBackground from "../actions/backgroundActions"
import setTransparentBackground from "../actions/backgroundActions"

// Which part of the Redux global state does our component want to receive as props?
const mapStateToProps = (state, props) => {
  return {};
};

const componentWillMount = () => {
  setRedBackground();
};

const componentWillUnmount = () => {
  setTransparentBackground();
};

// const actions = Object.assign(locationActions, lifecycleMethods);
export default connectWithLifecycle(mapStateToProps, {
  componentWillMount,
  componentWillUnmount
})(LogoPage);
// export default connectWithLifecycle(mapStateToProps)(LogoPage);

the backgroundActions:

const setBackground = backgroundClass => {
  return document.body.className = backgroundClass;
}

const setRedBackground = () => {
  return function(dispatch) {
    dispatch(setBackground("red-background"));
  };
};

const setTransparentBackground = () => {
  return function(dispatch) {
    dispatch(setBackground(null));
  };
};

export { setRedBackground, setTransparentBackground };

This doesn't even work, as I'd have to make up also redux actions, This to me seems to be a total overkill to have a dispatch for when I change the background color, and I don't need to have the background class stored in the redux repo.

But if I put the document.body.className = .. directly in the callback:

const componentWillMount = () => {
  document.body.className = "red-background";
};

I get an error saying that

Actions must be plain objects. Use custom middleware for async actions

What would be a more straightforward way to accomplish this?

EDIT:

my store.jsx

import { compose, combineReducers, applyMiddleware, createStore } from "redux";
import thunkMiddleware from "redux-thunk";

import nikeles from "../reducers/nikeles";
import location from "../reducers/location";
import page from "../reducers/page";

const store = railsProps => {
  const composedStore = compose(
    applyMiddleware(thunkMiddleware),
    window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  );

  const combinedReducers = combineReducers({
    location,
    nikeles,
    page
  });
  return composedStore(createStore)(combinedReducers, railsProps);
};

export default store;

Solution

  • In the end I solved it making the div of my LogoPage overlap the entire page.

    so that when it is shown I see the background as I want it, and when it gets unmounted the whole thing disappears easily, I like this solution as it is purely CSS.

    Here's my scss class for it:

    .logo-page {
        opacity:0.8;
        background-color:$my-red;
        position:fixed;
        width:100%;
        height:100%;
        top:0px;
        left:0px;
        z-index:1000;
    }