Mobx. Getting value from another store - reactjs

I have Mobx FirstStore and import SecondStore. SecondStore has a (value) and I want to use it (value) in my FirstStore.
As shown in the screenshots, this is how it works, but I have a question, is it safe to use it? If (value) changes in my SecondStore, will FirstStore see it?
Perhaps it is better to add a parameter and pass (value) through the React component when calling the function?
async someFetchRequest(valueFromSecondStore) {
await api.retData(valueFromSecondStore)
}
Thanks in advance!
======================================================================================

It is totally fine to use it like that in most cases.
There are cases when you might consider different approaches like Dependency Injection, or just pass values as parameters like you said. But until you encounter those advanced scenarios (make testing more approachable, for example, or server side rendering) you can safely use it like that. You can even make computed getter in the FirstStore, or reaction, with some value from the SecondStore and it will work as expected.
You can also encounter circular dependency loop in some rare cases if you import class A to class B and class B to class A, but if you only import them one way you are fine.

Related

How to prevent refresh of list over API after drag & drop with beautiful DND?

I simulated my Context + DND problem in https://codesandbox.io/s/adoring-booth-33vqo . I have other components which will be added to this example and I will use a Context hook to share values across the page.
After the initial render, everything looks fine. The idea of the list is to change the order within itself and when ones changes the order with drag-drop, it throws an "Invalid Hook" error.
So the (first) real question is, what is triggering this error which is linked to the line
const { lang1Library, updateLang1Library } = useContext(LangContext)
;
Thanks in advance for your help.
Geo
It's not a good approach to provide a link for the whole project even if it is small. But I had a quick look and there's at least one thing you're doing wrong:
// DragEndFct.js
export default function DragEndFct(result, libName) {
const { lang1Library, updateLang1Library } = useContext(LangContext);
This is not React component, but it uses a hook - and it is wrong. Hooks have a special meaning in React and should be used properly (Rules of Hooks).
You can't use hooks inside regular functions and expect them to work. That is why you are getting that error.
So, there are many ways you can try to fix this. For instance, DragEndFct is a regular function, you can declare more arguments and pass stuff you get from context:
// you are using it in components right ?
function DragEndFct(result, libName, param3, param4) {}
// so you probably have access to the context there
// and can pass data from the context when you call it.
// something like this
onDragEnd={function (result) {
console.log();
DragEndFct(result, StaticVars.LANG1_LIBRARY_NAME, lang1Library, updateLang1Library);
}}
You could even make DragEndFct to be a React component - it can just return null (which means no UI will be rendered) but in that case you will have hooks and all other stuff there. It really depends on what you need and how you will use it.

Redux hooks in regular function (rules-of-hooks)

I'm having a trouble with a regular function. In my component, I'm loading lot of products with a function that is reusable everywhere. So I have a file named products.js where some functions are defined.
In a function called 'getPrice', I need to get a param called 'beautifullPrice' stored in the redux store, on a reducer.
If I do it respecting hooks rules, I have to implement useSelector in my components and pass 'beautifullPrice' as a param in every functions. But my 'getPrice' is a sub sub sub call. So I need to declare 'beautifullPrice' in tons of functions, and this param cant change till the application is not reloaded.
So, in my opinion, the easiest way to do this is to use useSelector directly in my function 'getPrice', all my functions wont have one more params, it will be cleaner. But according to react-rules, I should not do this.
First question : Why this rule ? I tried and it seems to work well.
Second question : Is there an other proper way to do this ?
Am I the only one facing this type of problem ? =D
Thx for reading, and for help !

React, ESLint: eslint-plugin-react-hooks shows incorrect "missing dependency"

Assume you are using React and you are writing a custom hook useSomething that returns the identical same thing each time it is invoked for the same component.
const something = useSomething()
// useSomething() at time X === useSomething() at time Y
If you now use this something value inside of a useEffect(() => ...) and you do not pass something as a dependency to the array of the second argument of useEffect then the linter will warn you:
React Hook useEffect has a missing dependency: 'something'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)
Of course ESLint cannot know that something will always stay identical (per component), but adding not-changing things like something to the dependency array of useEffect each time they are used is really annoying. Just deactivating react-hooks/exhaustive-deps does also not seem to be a good solution (nor using // eslint-disable-next-line react-hooks/exhaustive-deps).
Is there a better solution than to add things like that unnecessarily to the dependency array of useEffect just to make the Linter happy?
Please find a simple demo here:
https://codesandbox.io/s/sad-kowalevski-yfxcn [Edit: Please be aware that the problem is about the general pattern described above and not about this stupid little demo - the purpose of this demo is just to show the ESLint warning, nothing else]
[Edit] Please find an additional demo here:
https://codesandbox.io/s/vibrant-tree-0cyn1
Here
https://github.com/facebook/react/issues/14920#issuecomment-471070149
for example you can read this:
If it truly is constant then specifying it in deps doesn't hurt. Such as the case where a setState function inside a custom Hook gets returned to your component, and then you call it from an effect. The lint rule isn't smart enough to understand indirection like this. But on the other hand, anyone can wrap that callback later before returning, and possibly reference another prop or state inside it. Then it won’t be constant! And if you fail to handle those changes, you’ll have nasty stale prop/state bugs. So specifying it is a better default.
So maybe just adding that never-changing values to the dependency array of useEffect may yet be the best solution. Nevertheless I hoped there would be something like a ESLint react-hooks configuration possibility to define a list of hook names which whose return values should be considered as static.
The example is a little contrived but I suspect you may wish to create a new useEffect block without this dependency.
If the store is not changing though I'd question why you'd wish to console log it time. If you wish to log it only on change then you'd add someStore to your dependency array. It really depends on what you're trying to achieve and your seperation of concerns.
I'd argue that if someStore is used as part of whatever logic is handled in this effect then it does belong in your dependency array.
You could also alternatively move const something = useSomething() into your effect and extract it as a custom hook link
useEffect(() => {
console.log("Current state (may change)", someState);
}, [someState]);
useEffect(() => {
console.log("Current store (will never change)", someStore);
});

need help for prev and next button in react

How to call back the effect operation when clicking the prev button using method or function with fullcalendar4 in react?
At present, I can only think of this way:
componentDidMount(){
document.querySelector('.fc-prev-button').addEventListener('click', e => {console.log(e)})
}
componentDidMount(){
document.querySelector('.fc-prev-button').addEventListener('click', e => {console.log(e)})
}
Looks like it works with React. Have you read some docs here about callbacks, or here specifically working with react and the underlying calendar's ref?
I've created a simple code sandbox that uses the callback style you try, and also using the API. Between the two, your method seems less recommended, but IMO is a little cleaner as it uses all the existing in-place UI, but is susceptible to being a little more brittle as the class names could potentially change, whereas using the API for next/prev these are calling methods directly so less likely to change.
I guess it depends a lot on what exactly you're trying to accomplish here, but what you have will "piggyback" off the button click, so if you're just trying to do something on the side it'll work.

Update Events in React : order?

Suppose I have something like this where both components A and D listen to changes in a global store :
import React from 'react'
import useStore from 'whatever-global-store-manager'
function A() {
const [store] = useStore()
if(!store.currentUser)
return <h1>You must log in</h1>
else return <B/>
}
function B() {
return <C/>
}
function C() {
return <D/>
}
function D() {
const [store] = useStore()
console.log(store.currentUser) // Can it be falsey ?
return <h1>{store.currentUser.name}</h1>
}
In A, when currentUser is falsey, B is not rendered, thus D is not rendered. But suppose this scenario :
At first, currentUser is defined as an object with a name property, so D renders, listens to changes in the store and renders the name.
Then, somewhere else in the app, currentUser is set to null.
In which order are the "listeners" processed ? Is there any chance that function D is executed with currentUser to null even when begin ultimately removed from the component tree ?
Another way to formulate the question : Should I check against currentUser in component D before accessing its name property ?
I was looking in the doc for a rule like "When two components listen to the same event, the one higher in the hierarchy is rendered first, and if it turns out the second one should be unmounted according the first's output, then the second one is never even called", but couldn't find anything. In practice, I know it works, but I would like to be sure that it's not just luck.
I believe this largely depends on the store observer mechanism, so it's hard to give a conclusive answer without knowing which store you're using. If observers are registered in order, that might affect how you need to deal with it.
If you wanna find out for sure, you could console.log your render methods, or use debugger while changing the value of currentUser.
Analysis of a hypotetical implementation: let's say an observer is registered when the component mounts, and unregistered when it unmounts. In this situation, the component A would trigger first (since it was registered first), and cause D to unmount, unregistering his trigger. In this hypothetical scenario, D wouldn't need to check for null.
Unrequested advice: a good thing for you might be centralizing the "data collection" in one parent component, while the children just receive that as props and render (without observing the store). I've found (both from lore and personal experience) that it simplifies a lot the development process.
Another way to formulate the question :
Should I check against currentUser in component D before accessing its name property ?
Yes, it is definitely a good decision: it is preferable that there is one redundant code line, instead of obtaining an error.
I was looking in the doc for a rule like
"When two components listen to the same event,
the one higher in the hierarchy is rendered first...
I think the opposite. Although I neither could find the specific documentation to explaine it, I remember that Components do not update like a cascade. That is the idea of the component oriented programming: each one is an independent entity.
Note: if I understand your example well, you could test this example by adding a setTimeout that wraps the return of function A, right? So this way you can then set currentUser as null and D wil be still rendered and you can see what happens.

Resources