Redux state value globally - reactjs

I am having a helper class which provies info about the logged in user. I would like to have it as a static method and use it in several places ( which are not react components)
How to get access the redux store value in a class model ?

If you can manage this in your application it would be cleaner (and more testable) to pass it around with dependency injection (DI) as opposed to using a global variable, static or singleton. In a simple form you could just pass it in the constructor like this:
var store = createStore(...);
var app = new AppClass(store);

If you're not using a bundler like Webpack, Lukas Katayama's answer should work window.store = createStore(...) but if you are using one, you can also expose your redux store by exporting it and importing where you need it.
//store.js
export const store = createStore(...);
//other file
import { store } from './store.js';
const someFuncOrClass = (...) => {
const user = store.getState().userInfo;
}

One way could be set a global variable
window.store = createStore(...)
and use it, accessing window.store

Looks like a straight forward implementation. You can create a getter for store in the same file where you creatStore(...).
store.js
import { createStore } from 'redux';
let store = {};
export default function store(...) {
/*
* things to do before creating store
*/
store = createStore(...);
return store;
}
export function getStore() {
return store;
}
helper.js
import { getStore } from './store';
export function getUserInfo() {
const store = getStore();
const globalState = store.getState();
return globalState.userInfo;
}

Related

React testing use mockstore with custom store to test it

I would like to test components that are using redux store in my project. Here is the function that I use fo getting some store elements:
const variable = store.getState().serverConfiguration.testValue;
When I am testing this component I use mockStore to do that so my store is empty right? That is why I get error saying that TypeError: Cannot read property 'testValue' of undefined
Is there a way to pass my custom store to mockStore so that it will be possible to test it correctly?
I tried to do that like this but it doesn't work:
const store = configureMockStore()({
serverConfiguration: {
testValue: "Admin"
}
});
Try this:
import configureStore from "redux-mock-store"
const mockStore = configureStore([]);
const store = mockStore({
serverConfiguration: {
testValue: "Admin"
}
})

How to communicate between Mobx stores created with React.createContext

I have my useStores.ts file which has two Mobx stores initialized in the following way.
import StoreA from "./stores/StoreA";
import StoreB from "./stores/StoreB";
const storesContext = createContext({
storeA: new StoreA(),
storeB: new StoreB(),
});
export const useStores = () => useContext(storesContext);
So I can use these stores inside any components in the following way.
const { storeA } = useStores();
But I'm not sure how to access storeA inside storeB.
Can someone please help me with the same?
You should create a root store that contains all other stores, and it passes itself to the child stores, so they can "go up" to the root store, and then to any other store.
class RootStore {
storeA = new StoreA(this)
storeB = new StoreB(this)
}
class StoreA{
constructor(rootStore){
this.rootStore = rootStore
// get to store B
// this.rootStore.storeB
}
}
Use with createContext
const storesContext = createContext(new RootStore());
Or even better, follow the dependency injection principles and pass child stores to root store in the RootStore constructor.
class RootStore {
constructor(a,b){
this.storeA = a
this.storeB = b
this.storeA.setRoot(this)
this.storeB.setRoot(this)
}
const storesContext = createContext(new RootStore(new StoreA(),new StoreB());

How do I access the redux store from a helper class or function

I have the access token stored on the Redux store and I want to send it with each API request where authentication is needed. I have a class for API functions. Which is kind of a library. I am not sure how I can access the token from the API class.
Can anyone help regarding this?
You have to import store in the file you need to access the store from your respective index file, i have done it like this
import { store } from '../index';
store.subscribe(() => {
store.getState();
token = store.getState().Login.token; //access token here
})
In the index.android.js/index.ios.js i have exported store
export const store = createStore(
RootReducer,
undefined,
// the ordering of middleware is significant.
applyMiddleware(thunk),
);
If you need have access from your component and considering you have a reducer called user and in your initial state you have something like this:
const INITIAL_STATE = {
logged: false
}
1. import { connect } from 'react-redux'
Create your mapStateToProps like:
const mapStateToProps = (state) => {
return {
logged: state.user.logged
}
}
As a good practice create a prop in your component:
MyComponent.propTypes = {
logged: PropTypes.bool
}

How to connect component (file) to redux store

I need to create component/file/class whatever and connect it to redux store.
I don't need this component to be rendered.
It's just a helper component which can contain methods that return value from store.
I tried to create a file with:
export function getKeyFromReduxStore(key:string) {...
but this is just a file that export function and I can't (or don't know) how to connect it to redux store.
All my components are connected with store throught:
<RouterWithRedux>
<Scene key="root">...
but as I said this is no scene it's just helper component that I want to reuse through whole app.
How can I make such a component and connect it to redux?
Redux store has a method called getState which gets the state of the store. You can import the store you have created in the file where redux store is required.
// in the file where you created your store
import { createStore } from 'redux';
export const myStore = createStore(
// ... some middleware or reducer etc
)
// in your component/file/class
import { myStore } from '../path/to/store'
export function getKeyFromReduxStore(key:string) {
return (myStore.getState())[key];
}
Alternatively, you can pass in the store to getKeyFromReduxStore function and call it in react component where store would be available. For instance in the mapStateToProps function:
// component/file/class
export function getKeyFromReduxStore(store, key) {
return store[key];
}
// react component with access to store
import { getKeyFromReduxStore } from '../path/to/file';
class MyKlass extends Component {
// ... your logic
render() {
const val = this.props.getKey(someVal);
}
}
const mapStateToProps = (state) => ({
getKey: (key) => getKeyFromReduxStore(store, key),
})
export default connect(mapStateToProps)(MyKlass);

Accessing redux store inside functions

I would prefer to have a function exposed from a .js file , within that function I would prefer to have access to the variables in the store.
Snippet of the code : -
import { connect } from 'react-redux';
function log(logMessage) {
const {environment} = this.props;
console.debug('environment' + environment + logMessage );
....
}
function mapStateToProps(state) {
return {
environment : state.authReducer.environment
};
}
export default function connect(mapStateToProps)(log);
I have many components, which attach the class through connect, can I attach functions through connect()?
Edit 1
Some_File.js
import store from './redux/store.js';
function aFunction(){
var newState =store.getState();
console.log('state changed');
}
store.subscribe(aFunction)
I am assuming you have created store and reducers as redux expects.
~~~~~~~~~~~~~~~
Original Answer Starts
This is a sort of hack, I don't know what you are doing so I can't say you should or you should not do it, but you can do it this way. I have copy-pasted some of your code with some modifications.
Class XYZ extends React.Component{
componentWillReceiveProps(props){
//in your case this.props.storeCopy is redux state.
//this function will be called every time state changes
}
render(){
return null;
}
}
function mapStateToProps(state) {
return {
storeCopy : state
};
}
export default function connect(mapStateToProps)(XYZ);
Put this component somewhere at top, may just inside provider, whenever state changes this componentWillReceiveProps of this component will be invoked.
If you have a pure functional component then you can access the redux state directly like this:
import store from './redux/store';
function getStoreDetails() {
console.log(store.getState());
}
The proper place to access the store is through a container, connect is used to connect a container to a component, you cannot connect a random function to it.
There is a logger middleware for redux that you might wan't to take a look at, it does what you're trying to achieve.
To use it, just pass it as a middleware to your store:
import createLogger from 'redux-logger';
const store = createStore(
reducer,
applyMiddleware(logger)
);
A more proper way to debug a redux app is to use React Dev Tools, if you use Chrome, I recommend you to use the React Dev Tools Extension. Just install it and use it as a middleware
let store = createStore(reducer, window.devToolsExtension && window.devToolsExtension());
With it, at any given moment you can see the whole state of your store, see the actions being fired and how they affect the store, and even rewind your application by un-doing actions.
Yes. You can attach functions via connect as below;
const mapDispatchToProps = (dispatch) => {
return {
testFunction: (param1) => dispatch(testFunction(param1)),
testFunction1: () => dispatch(testFunction1())
};
};
export default function connect(mapStateToProps, mapDispatchToProps)(log);
redux state can be accessed as prop in a function by using below format.
1:
import { connect } from 'react-redux';
// log accepts logMessage as a prop
function log(props) {
const { environment, logMessage } = props;
console.debug('environment' + environment + logMessage );
....
}
function mapStateToProps(state) {
return {
environment : state.authReducer.environment
};
}
export default connect(mapStateToProps)(log);
How to use log function?
log({ logMessage: "Error message" });
2:
// import redux store
import { store } from './Store';
function log(logMessage) {
const currentState = store.getState();
const environment = currentState.authReducer.environment;
console.debug('environment' + environment + logMessage);
....
}

Resources