-
-
Notifications
You must be signed in to change notification settings - Fork 85
Support property-specific callbacks. #148
Comments
FYI, this is a sketch of a utility method for subscribing to reactn state properties assuming the use of providers. It uses
Then, in a utility method/helper code, you can subscribe to a reactn state value by doing something like:
|
Thank you for the great idea. This middleware between the callback and your utility may help:
I wrote it free-hand, so sorry for any bugs, but it should be enough to get you started. I'd like to see |
@CharlesStover Thanks for the reply! My only concern about the middle-ware solution you provided is the equality statement you wrote. Were you only intending it for simple data-types like string/numbers? I don't think |
The only time this would be a problem is if you copied the object/array but did not change any values. A reference of an object to itself is considered equal.
In ReactN, these values will be the same each render. The only time they would change is if you change them, but set them to the same value:
The second example is false because B is a new array that just copies A. If A is your global state array, it should not change between renders. It would only "change" if you did something like this:
Hope this helps. There are a lot of utility libraries out there for doing shallow and deep comparisons of objects and arrays. These may be useful for handling your edge-cases. |
Thanks so much for your middleware idea, I was able to come up with a utility function based on that and I was able to remove the need for rx-js. The key difference is that my function allows you to specify as many or as few properties as you want to listen to: import ReactNProvider from 'reactn/types/provider';
import { isEqual } from 'underscore';
type IPropertyConfig<StateType> = {
[P in keyof StateType]?: (
nextValue: StateType[P],
lastValue: StateType[P]
) => void;
};
export function createPropertyCallback<StateType>(
provider: ReactNProvider,
propertiesObj: IPropertyConfig<StateType>
) {
const lastValues: Partial<StateType> = {};
const properties = Object.keys(propertiesObj).map(property => ({
property,
callback: propertiesObj[property]
}));
properties.forEach(({ property }) => {
lastValues[property] = provider.getGlobal()[property];
});
return globalState => {
for (let prop in lastValues) {
const nextValue = globalState[prop];
const previousValue = lastValues[prop];
if (!isEqual(nextValue, previousValue)) {
lastValues[prop] = nextValue;
properties
.find(x => x.property === prop)
.callback(nextValue, previousValue);
}
}
};
} A couple differences in mine...
I only use ReactN with Here's how you use it: interface ITestState {
count: number;
status: string;
dontCare: string;
}
const TestState = createProvider<ITestState>({
count: 0,
status: 'hello, world',
dontCare: 'not interested in this one'
});
TestState.addCallback(
createPropertyCallback<ITestState>(TestState, {
count: (n, p) => {
console.log(
'count changed',
`previous value: ${p}`,
`next value: ${n}`
);
},
status: (n, p) => {
console.log(
'status changed',
`previous value: ${p}`,
`next value: ${n}`
);
}
})
); |
Thank you very much for the contribution. I hope others find it and resolve their similar issues. I'll leave this open as a note for the official implementation, but I don't see it happening anytime soon, as I mentioned earlier. :) |
Hi there,
I am looking for a way for code that is not within a component to subscribe to change to state, akin to an rxjs Subject. I have some api code that needs to make use of a Provider state that has the current path to the host, and if the path changes, it needs to be able to respond accordingly.
Currently,
addCallback
is my only option, but I have to set up manual checking for if the state property I am concerned about changes, and it feels a bit clunky and unnecessary to be executing on every state change.Am I missing any current capabilities that would work for this situation? Perhaps something in
addCallback
that gives detail on what state changed?Thanks!
Matt
The text was updated successfully, but these errors were encountered: