0

I having an issue with the Redux store in getting react_on_rails where I want to switch the page and it doesn't work correctly for me. I am losing the redux store if I change the page or reload it. Also, I am sorry for a pile of code I put, but I really don't know anything else or ways to fix it, the official docs for react_on_rails and redux did not help me and it more likely confuse me how it should work. if anyone has a clue how to make it work, in advance, thank you

rootStore.js

import { combineReducers, applyMiddleware, createStore } from 'redux';
import middleware from 'redux-thunk';

import reducers from '../reducers';

export default (props, railsContext) => {
  // eslint-disable-next-line no-param-reassign
  delete props.prerender;
  const combinedReducer = combineReducers(reducers);
  const newProps = { ...props, railsContext };
  return applyMiddleware(middleware)(createStore)(combinedReducer, newProps);
};

reducers/index.js

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';

import cartReducer from './cartReducer';

const rootReducer = combineReducers({
  routing: routerReducer,
  cart: cartReducer,
});

export default rootReducer;

the component that I am trying to do magic with

// @flow

import * as React from 'react';
import { connect } from 'react-redux';
import { addToCart} from '../actions/setCart';
import styles from './AddToCart.module.scss';

type Props = {
  productId: number,
}

type State = {}

class AddToCart extends React.Component<Props, State> {
  constructor(props: Props) {
    super(props);
  }

  onClick = () => {
    console.log(this.props.productId);
    this.props.addToCart(this.props.productId);
  };

  render() {
    console.log('this.props.cart', this.props.cart);

    return <button
      onClick={this.onClick}
      className={styles.button}
    >Add To Cart</button>;
  }
}

const AddToCartRedux = connect(
  state => ({
    cart: state.cart,
  }),
  dispatch => ({
    addToCart: id => {
      dispatch(addToCart(id));
    },
  }),
)(AddToCart);

export default AddToCartRedux;

my entry point

import ReactOnRails from 'react-on-rails';
import ProductDetailPage from '../pages/ProductDetailPage';
import rootStore from '../store/rootStore';
ReactOnRails.setOptions({
  traceTurbolinks: true,
});
ReactOnRails.register({ProductDetailPage});
ReactOnRails.registerStore({rootStore});

my layout application

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>

  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>

<body>
<%= notice %>
<%= alert %>
<%= redux_store('rootStore', props: {}) %>
<%= react_component('ProductDetailPage', props: {product: @product.id}) %>
<%= yield %>

<%= redux_store_hydration_data %>
</body>
</html>
GYTO
  • 440
  • 1
  • 10
  • 23
  • 1
    You seem to be conflating two different issues. The first issue is that the redux store (which is stored in a Javascript variable) is lost when you reload the page. That's expected behavior. If you want it to persist state through reloads, you need to save the parts of the store you care about somewhere, such as [local-storage] or [cookies]. The second issue is about using a router so you don't have a full page load when a link is clicked. Travis has addressed this in their answer. – Conspicuous Compiler Mar 20 '19 at 04:13
  • @ConspicuousCompiler I am new to redux and I had already several issues with it. The more question to saving the store would be using `redux-persist`, correct? as far as I understand it will save data to the `indexedDB` and then I just can retrieve when I needed. Due to the `local-storage` or `cookies` has a limited amount of storage to use. So coming back to the main question, am I going on the right path with `redux-persist`? – GYTO Mar 20 '19 at 18:04
  • If you're pushing against the storage limits of local-storage, I'd be concerned a bit about the managability of your state, but what solution you choose in that regard is an architecture call. There's no hard and fast answer. – Conspicuous Compiler Mar 20 '19 at 19:02
  • @ConspicuousCompiler the option that I was thinking to use in an above problem that I can use `redux-persist` to store my rootStore, then using the functionality of redux-persist and `localforage` lib to save everything to IndexedDB as json which I can retrieve any time from storage. I had a one-time edge case where localStorage was not an option to save a json file. On the other hand, this project is not required a lot of data to be stored. – GYTO Mar 20 '19 at 19:10

1 Answers1

1

Since the Redux store is initialized when you load a page, navigating to a new page or reloading the page will cause all your JS assets to reload and re-initialize, causing your store to reset.

If you want to change the browser's location without a page reload, you would need to use something like react-router to handle navigation between React components instead of going through a full request/response cycle with the Rails server.

Travis Haby
  • 150
  • 1
  • 6