I have some variables which are controlled by React Context through React.createContext() inside a functional component. I'm also using redux-saga, so my question is are there anyway to access this context value in redux-saga function. Storing the values in Saga middleware isn't an option bcoz, the context values keeps changing.
The only option I have is to pass the context value to action object payload when dispatch an action. So in redux-saga, we can use it in action parameter.
I have visited this link for Class component, which doesnt work for Functional components.
Access context data in sagas
Yes. I finally created a package to get around this, just use useContext when creating the call config.
https://github.com/alisternorris/react-outside-call
Related
I have a react project configured with redux for state management.
For api calls I use a file called axiosInstance. In this file I need to have access to redux store (and I have access importing store and using getState - store.getState()). Now the problem is that I want also to update the redux state from this file (axiosInstance).
How I can update redux store from this file (which is not a react component) in a efficient method?
Okay, I assume that you are using Axios for the network calls.
tl;dr
Use store.dispatch(action) and action to make changes to store state
Yes, the store can be accessed with store.getState(), you can also change state with store.dispatch(action). as per the docs
Dispatches an action. This is the only way to trigger a state change.
The store's reducing function will be called with the current getState() result and the given action synchronously. Its return value will be considered the next state. It will be returned from getState() from now on, and the change listeners will immediately be notified.
This happens because of the functional paradigm that redux follows (google for more).
Now, the action has to be defined with an actionCreator, or simply you could call .dispatch() with an inline object with one string property as {type: 'name-of-action'}. This prompts the store to change the state.
You may require redux-thunk for async actions.
Conclusion:
Let's save some trouble here as you may have many calls to the store, you can create a context that handles the AxiosInstance (as there is already a different file for that).
Make a context in the AxiosInstance file and then you can start dispatching actions as per the network responses. this will save you a lot of trouble as the state is updated by redux without actually looking at it much.
Let’s say I don’t use Redux (and therefore no Redux Thunk involved) in my application, and instead, I manage my state with the useReducer hook.
The issue is that in the action creator, I want to access the state itself. Does the only solution is to give the state itself as a parameter to the action creator, or is there a way to get the same benefits of the Redux Thunk, and be able to access the state itself through some getState() function?
Create a reducer that accepts state & action and returns a new state based on the action (same as redux).
When you are calling 'useReducer' you should pass it the reducer you've built and the initial state.
You will get back the state and dispatcher (the function that will use you to update the state - same as redux).
Please find the following articles explain how to achieve it shortly and simply:
https://www.peanutbutterjavascript.com/roll-your-own-redux-with-usecontext-usereducer/?fbclid=IwAR2je-sa5UW_5elE8UlkcUfZEzYjiwBO44P4smsn3NPznUiMS3EZEKsILEw
https://medium.com/#martin.crabtree/react-creating-a-redux-like-global-state-with-the-usecontext-and-usereducer-hooks-89aa2b27dbc5
What would be the best way, while following React best practices, to define globals that changes according to props provided by a redux state.
For example, let's say I have a metric or imperial toggle value that's dispatched into a persisted redux state. Is it possible to call for a constant that changes its value based on the toggle without providing the current state of the toggle by passing it via props?
My current implementation is doing
globals.distance(this.props.metric)
where this.props.metric is mapped from the redux state to the component's props. I want to somehow implement subscription to the redux state from within the globals file, so I can just do constants.distance. I've tried importing getState() as well as subscribing to changes in the redux state, but the problems there is that getState() only runs once when the file gets loaded, and I can't seem export constants subscribed to the state since the function returns an unsubscribe function. I can also create a Component and subscribe that to the redux state, but I can't seem to find an easy way to export constants from within a Component state either.
Well, I couldn't find a solution I liked, so I made my own. It's a thin wrapper to connect functions to the Redux store and return a value.
I am new to React and want to understand the difference from classic MVC.
I want to create a simple components that loads some data initially and renders let say a grid.
On some state or prop change it will reload the data and re-render.
What is the best approach in react from below two options?
using the lifecycle events to load the data, update some state and render while in another event will show some loading opacity.
Work with redux and react-redux? but in all example I cant see API calls.
Is this the role of a middleware (Thunk?)?
Will appropriate an explanation.
Both the approaches are correct. It depends on your use case. If you can avoid using redux in your app, use the lifecycle methods to make API calls (also called subscriptions in react documentation). If you think your app has many components and different components needs to share a state, then use redux.
You should also look at React hooks https://reactjs.org/docs/hooks-reference.html
You can use Effect Hook https://reactjs.org/docs/hooks-effect.html to make API calls and update your component's state.
Update:
Both Thunk and Sage are used to manage side effects in your application (making API calls from here). I've used saga, I don't know much about thunk.
How you would use redux-saga:
Say if you want to get some data for display on a button click, this is how it works:
On button click you dispatch an action, say GET_DATA
Your redux reducer will change some state on this particular action, say isLoading=true
You can use isLoading in your component to show a spinner/overlay
At the same time saga will listen to GET_DATA action and make the API call
If success, from Saga you'll dispatch an action, say GET_DATA_SUCCESS with the data from API call
Reducer will change isLoading=false and set the data in state, say apiData = { ... }
If failure, from Saga you'll dispatch an action, say GET_DATA_FAILED with the error code/message
Reducer will change isLoading=false and set the error in state, say apiError = { ... }
You can now use isLoading=false in you component to remove spinner and display the data (apiData) or error (apiError) in you component.
You can go through this tutorial to learn more https://redux-saga.js.org/docs/introduction/BeginnerTutorial.html
Let's say I have this code below:
switch (action.type) {
case "GET_LIST":
// update state
break;
case "GET_LIST_SUCCESS":
// update state
break;
case "GET_LIST_ERROR":
// update state
break;
default:
return state;
}
Before this, I've already set-up some action creators (with a thunk middleware for async requests). So the flow would be either GET_LIST > GET_LIST_SUCCESS OR GET_LIST > GET_LIST_ERROR.
Now in my React component, I want to do something depending on which action type was dispatched in the end (either success or error).
Is it a good practice to use the action type themselves or should I just use the store state for my condition? In this example, my store would have an error property, which I can use to detect whether there's an error or not.
So it's either (using action type):
if (actiontype === "GET_LIST_SUCCESS") {
// do something
}
OR (using the store state)
if (this.props.list.length > 0) {
// do something
}
Which is a better practice and why?
Just my opinion, but one advantage of using Redux over storing data in component state is that you separate the concern of how to handle data updating from view layer (React) to Redux; React component should only know if the data has been changed, not how it is changed. This de-couples the data layer and view layer in frontend, and helpful when you need to execute a chain of actions to update state (e.g. fetching from API).
If you want to expose current Redux action type to React component, you have to log the action somewhere in your app, since I don't think Redux exposes current action to view layer. In addition, this also reveal too much info of how Redux handles data flow.
Common practice is saving fetching state in boolean, and error log, e.g. isFetching and fetchListError, update those values along the fetching process, and pass those value to view layer for display.
From my understanding, we have react app with components and redux app with store. We use
another library react-redux to bind react app and redux app. React-redux helps to use redux store state in react component and helps to dispatch actions to redux store from react component.
For handling asynchronous operation libraries like Redux-thunk is used and depending on the result of the asynchronous operation, these libraries dispatch action.
Answer to your question: React is not aware of which action was dispatched in Redux store as it is handled by thunk middleware. But using React-redux, React can know what is the current Redux store state after the action was dispatched by thunk middleware. So I think you shoud go with the second option. First option might be possible but it will need alot of hacking than simply using the first one.