One of my redux actions requires access to a class that manages api requests.
However in my api requests class, I wrote a method that requires importing the data store. I then began getting the following error:
Cannot access 'WEBPACK_DEFAULT_EXPORT' before initialization
I looked up the error and mentions It is due to a dep cycle, it seems that this pattern is causing the importing of an uninitialized data store.
summery: Since my redux slice imports the api class and the api class depends on the redux store how can i restructure my code to fix this pattern?
We specifically advise Redux users that you should never import the store directly into other files, except the main app entry point file, because of this sort of import cycle problem.
The best approach here would be to restructure your logic so that this class file doesn't need to use the store at all.
As a secondary fallback, you can expose a setter from that module that saves the store reference, and call that setter from the entry point on startup.
Related
Where should I put get user data API call which is requesting user data such as username, email from JWT token stored in localstorage.
Should I call it from _app.js pass it to the components or should I create redux store and save these data.
Using redux only for that purpose is an overkill. You should create context and wrap components, which are using this data. Also there is hook called useReducer, combined with context API allows you to achieve redux behavior.
Passing user data down to components directly is not a bad idea if you have only 2 level depth structure which is often not the case.
For this purposes is a nice option to use tools like Redux or React Context API. That way you can access the global state from whichever component you like in the same way, which leads to more readable and maintainable code. For more information about Redux vs Context API, consider looking more in-depth to understand the differences and decide which one is more suitable for your case.
For me personally, the Context API can do the work in more of the cases which is fine. Also, it is already part of React, and it's not a dependency like Redux is.
I have a global toast, which I am opening using redux slice. I need to open the toast for error message when call from api fails in api-slice of rtk-query.
I have seen the answer, using store.dispatch method, but this causes dependency cycle. Is there a way to do this?
Yeah, you should always avoid directly importing the store into other application files.
Ideally, none of the rest of your code would ever need to refer to store directly.
Depending on where in the RTKQ setup you need to trigger this toast, you may have access to dispatch as part of the lifecycle function arguments.
In the worst case, you can use our fallback recommendation to inject the store into the necessary files from the app setup logic.
I'm using axios.get() to call an api endpoint in one of my components. I need the ability to encapsulate this endpoint call so I can reuse this implementation by calling it from several different components.
What is a generally acceptable way to structure this type of implementation in a React project? For example, would it be generally acceptable to group related api calls into js files in a src/services directory at the same level as src/components?
It would be acceptable to create a utils or services directory and group related API calls. However it is important to remember that with async requests you need to consider the components calling the api service utils might un-mount. This might result in warnings or errors if not handled properly. A possible way to handle this might be to only execute callback functions if component is still mounted tracked via a state variable in a useEffect hook.
A more modern react approach might be to leverage hooks and react context for data handling. You could create a DataContext with a useReducer hook to fetch or push data for example.
(see https://reactjs.org/docs/context.html)
There are many way to do this.
Redux. It's old way is that you need to use redux style.
Hooks. Starts from React 16.8 version.
I will recommend to you use hooks. It's more useful and guarantee true way.
3 years ago i lived in Redux paradigm and every time write the monkey code thinking about consistent Redux store state.
Please try this one react-async package.
This is more of an understanding question and I also want to know the community thoughts, rather than a code question.
We have a React App using redux for managing the global store and redux-thunk for dispatching actions. Now we want to localize the App and add a language switch. For that purpose I created a HOC which uses React.Context to store the dictionary for current language in it. And I wrapped all Components in this HOC - everything works just fine.
But we also need to access to the dictionary in the thunks to e.g. provide success/error messages after API calls in the selected language. It seems to be impossible without passing dictionary into thunks.
I've read a lot about Context API and when to use it and that it has different purpose than Redux. That's why I put the translations in the Context and not in the store, mainly for this reason. But now I'm getting the feeling that I missed something and should actually put the translations in the store instead to not be forced to pass the dictionary to the thunk every time I need it there. Is it so?
Or is there a way to implement something like getContext similar to getState from redux-thunk?
I tried searching for "good practices" about how to link complex APIs that needs configuration or be provided by some manager and I can't seem to find how to make a "good" flow of data through redux.
So far I have been thinking of creating a reducer with actions that map each method I can call on a given complex object.
To put more context to it, I am building a framework to interact with a bluetooth device using this library (https://github.com/Polidea/react-native-ble-plx) and the startScanDevice returns me complex objects I can interact with (https://polidea.github.io/react-native-ble-plx/#device) which also holds it's own state (a device knows if it's connected or not for instance, it also knows it's bluetooth services, etc.).
From what I have read, redux state should be having simple objects so it can have time travel properties and ease persistence.
What would be a good design to to store those complex objects and enable interaction between my components, reducers, actions, the store and this API I'm currently working on ?
Currently, I was thinking of giving callbacks to my API that would dispatch redux actions with new data to add in the redux store but I just can't seem to find a proper way to store my complex objects and provide access to it in order to invoke those methods and give them callbacks.
Here's a complete flow example :
Invoking startScanDevice from the plx-ble API and provide a callback to receive device object given by that existing API
receive device objects and store it somewhere
Update redux store with proper information about the device object I need throughout the app
From a reducer, retrieve the device object from step 2 and invoke a method to interact with the device (example read from a characteristic)
Update redux store with read data from step 4
Steps 2 and 4 are the ones I can't seem to find a proper way to do.
Any help would be greatly appreciated !
Redux-thunk middleware could be helpful to you.
Redux Thunk middleware allows you to write action creators that return
a function instead of an action. The thunk can be used to delay the
dispatch of an action, or to dispatch only if a certain condition is
met. The inner function receives the store methods dispatch and
getState as parameters.
to store those complex objects
Don't complicate this.Try to keep your state as flat as possible.
Like
state={
PoweredOn: false,
Device: "deviceName",
//similarly all
}
The more you keep it flat the more it will be easy to modify.
The API doc you linked seems to have duplicate ways of calling these methods for exactly this reason.
For instance, you could connect to the device by calling device.connect(options) or by calling the package method connectToDevice(deviceId, options). The benefit of the second method being that you only need to track the ID value, and have no need to store the entire device object.