Closed AlexanderLoshkarov closed 5 years ago
when I have to update my property
What do you mean by this? Are you updating some piece of UI? Or another variable in your component?
@ianobermiller yes, I'm updating UI.
@ianobermiller here is the simplified code which might clarify my intents
const mapState = useCallback( state => { //...code to read node from the store const value = getValue(node.path)(state); return { value: value, } } ,[ getValue(node.path)(store.getState()) ] );
@ianobermiller
in the application I have different inputs as custom components who constantly speaking to the server via persistent connection. So they send their input values and server processes them and respond with validation or calculation results as a commands which then dispatched to the store and updates those values matching their path/key. So I need to react on those values updates coming from the server and dispatched to redux, but I can't because useCallback is limited to the arguments from outside...
In other words I kinda don't understand the situation we limiting to read store updates by the arguments which might not belong to the store at all. I was thinking about the store like an observable collection to which we subscribe for updates receiving, but seems like now it is not.
Can you create a simple codesandbox demonstrating the issue? Another way to explain this that might help is showing how you would solve this with react-redux.
I'm still not really sure what you want to accomplish. Copying from Input.tsx:
const [localStateValue, setLocalStateValue] = useState("");
useMappedState(
useCallback(
reduxStoreState => {
const reduxStoreValue = reduxStoreState.processedValue;
if (localStateValue.value !== reduxStoreValue.value) {
setLocalStateValue(reduxStoreValue);
}
},
[localStateValue.value] // I wish I can have an access to reduxStoreState.processedValue here
//to pass it's value as a dependency
)
);
useMappedState
returns the value you should be using directly, and takes care of not re-rendering if that value hasn't changed. Your code could be as simple as:
const localStateValue = useMappedState(useCallback(
reduxStoreState => reduxStoreState.processedValue,
[],
));
How to pass values from redux store to useCallback as dependency arguments
It doesn't really make sense to do this -- the entire point of the callback is to select something from the store, so how could the callback itself be based on the store values? You can certainly select things from the store with useMappedState
and then put them in the dependency array of another hook.
I'm going to close right now, but I will reopen if our discussion turns up something actionable.
I'm still not really sure what you want to accomplish. Copying from Input.tsx:
const [localStateValue, setLocalStateValue] = useState(""); useMappedState( useCallback( reduxStoreState => { const reduxStoreValue = reduxStoreState.processedValue; if (localStateValue.value !== reduxStoreValue.value) { setLocalStateValue(reduxStoreValue); } }, [localStateValue.value] // I wish I can have an access to reduxStoreState.processedValue here //to pass it's value as a dependency ) );
useMappedState
returns the value you should be using directly, and takes care of not re-rendering if that value hasn't changed. Your code could be as simple as:const localStateValue = useMappedState(useCallback( reduxStoreState => reduxStoreState.processedValue, [], ));
Hi Ian, thanks! Your example is working well, I tried similar thing before, but seems like there was a bug in my sendbox, the input value was not changing, and I mistakenly thought that this happens because we supply an empty array as a dependency argument to the useCallback.
@ianobermiller Just want to clarify one last thing, that "connect HOC" from "react-redux" works more precise, because it composes in right direction. It happens that in our app we remove the parent node from the store to notify the application that edit form must be closed. So in JSX we check if the node does not exist we render null. That makes "react" to remove components tree from the DOM, and because "connect HOC" is a part of that tree it also safely unsubscribes from the store (I hope) , and does not react on store updates coused by parent node removal. This works differently for hooks. Because hooks do not participate in the components composition (not composed/nested into components tree, like "connect HOC") they're reacting to the store update earlier than components removal happened. That leads to one more redundant cycle and extra problem, like in our case we need to check if the parent exists or make a safer code, just not to get null pointer exception.
I have updated, the previous example, just to clarify that situation. Please feel free to share your opinion on that! Is there another way how to eliminate this redundant callback?
Sounds like you may be referring to top-down data flow, which this hook does not implement: https://github.com/facebookincubator/redux-react-hook#how-does-this-compare-to-react-redux
Hi Lads, Sorry, if this is wrong place to ask the question, please point me to the correct one. In my case I end up with situation when I have to update my property depend on the changes happened to one of the store values. Was looking through the tutorial and didn't find any solutions for this kind of cases. After digging a little bit deeper into original redux api I found that I can subscribe to the store directly and getState() outside of useCallback, read the necessary value and provide it as a useCallback dependency argument. But in that case, seems like it makes the useMappedState() redundant... Could you please help me to find the right way to sort this?