Closed jhsu closed 7 years ago
Same issue here, when try to compose 2 providers with the same component:
const counterStore = provideState({
initialState: () => ({counter: 0}),
effects: {
addCount: (effects, val) => state => Object.assign({}, state, {counter: state.counter + val})
}
});
const colorStore = provideState({
initialState: () => ({color: 'black'}),
effects: {
setColor: (effects, col) => state => Object.assign({}, state, {color: col})
}
});
const CounterChildComponent = injectState(({state: {color, counter}, effects}) => {
const handleClick = () => effects.addCount(1);
return (
<div className="childComponent" onClick={handleClick}>
<span>CounterChild ...</span>
<span>color: {color}, {counter}</span>
</div>
);
});
const ColourChildComponent = injectState(({state, effects}) => {
const handleClick = () => effects.setColor('blue');
return (
<div className="childComponent" onClick={handleClick}>
<span>ColorChild ...</span>
<span>{state.color}</span>
</div>
);
});
const ParentComponent = (props) =>
<div className="parent">
<CounterChildComponent/>
<ColourChildComponent/>
</div>;
export default counterStore(colorStore((ParentComponent)));
// ramda compose does not work either ->
// R.compose(counterStore, colorStore)(ParentComponent)
It's strange because when apply the colorStore in first place, you can update the colourChild but not the counterChild ...
... if you click on counterChild many times and then click on the color component, both states are updated
@jhsu, there's one problem with the code you posted, and that's probably the source of the problems you're encountering. The state update function is a synchronous function - it returns new state. However, your nextPage
state update function returns a Promise
. That's probably not what you intended. Something like this will work:
const serverData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const getData = page => {
page = page || 0;
return Promise.resolve(serverData[page]);
};
const withFetching = provideState({
initialState: () => ({ entities: [0] }),
effects: {
fetchPage: async (effects, page) => {
const pagedData = await getData(page);
return state => {
const entities = [].concat(state.entities);
entities[page] = pagedData;
return Object.assign({}, state, { entities });
};
}
}
});
const justPagination = provideState({
initialState: () => ({ page: 0 }),
effects: {
nextPage: async (effects, currentPage) => {
const nextPage = currentPage + 1;
await effects.fetchPage(nextPage);
return state => Object.assign({}, state, { page: nextPage });
}
}
});
const App = injectState(({ state, effects }) => {
const onClick = () => effects.nextPage(state.page);
return (
<div>
<div>entities: { JSON.stringify(state.entities) }</div>
<div>page: { state.page }</div>
<button onClick={onClick}>click</button>
</div>
);
});
so i'm trying to have two different
provideState
s for pagination, one that handles the pagination state, and one that does the fetching.This doesn't work, but I'd like to do something like that. Any suggestions?