rportugal / apollo-cache-redux Goto Github PK
View Code? Open in Web Editor NEWRedux cache for Apollo Client 2.0. This project is no longer maintained.
Redux cache for Apollo Client 2.0. This project is no longer maintained.
I'm pretty keen on trying a good Redux backed Apollo cache before upgrading to the new 2.0 client, so I'm very interested in how this project is going!
Are there any todos or glaring issues with this cache implementation? I'm heeding the warning in the readme although I plan on trying it out with a larger app soon to see how it performs.
I'd be happy to pitch in if there is a plan in place. Extending Apollo's cache makes a lot of sense since their strategy(I think?) is to allow many cache implementations to propagate. Thanks for making the first steps!
Is this being actively maintained? Will it ever be update to work with Redux 4.x?
ncaught (in promise) Error: Network error: Encountered a sub-selection on the query, but the store doesn't have an object reference. This should never happen during normal use unless you have custom code that is directly manipulating the store; please file an issue.
at new ApolloError (bundle.esm.js:60)
at QueryManager. (bundle.esm.js:1184)
at step (tslib.es6.js:97)
at Object.next (tslib.es6.js:78)
at tslib.es6.js:71
at new Promise ()
at __awaiter (tslib.es6.js:67)
at bundle.esm.js:1147
at bundle.esm.js:1627
at Array.forEach ()
Unfortunately I'm not available to continue maintaining this project, as I'm not currently involved in any projects that depend on it, and cannot keep it up to date and working to good standards.
I'd like to invite the community to help maintain apollo-cache-redux
. Please let me know if you're interested in continuing this work.
Currently it assumes thereβs a reducer named apollo
, even though you can create one with another name in the store itself.
What's the purpose of dispatching APOLLO_OVERWRITE
in the constructor for the cache? Given that the data
passed to it can only be the empty object passed in from here and the state is already initialized as an empty object in redux, it seems like a redundant call. Everything appears to work without it.
In an example of rehydrating redux state (including the apollo state), this action wipes out the state, which then has to be reinitialized with a call to ReduxCache#restore
which also dispatches APOLLO_OVERWRITE
. Outcome is 2 actions for the same result as none.
Not a huge issue in 99% cases, but this actually breaks a niche use case in our RN app where we synchronize the state with a WebView's.
We're forking for now with this change. More than happy to open a PR if this is erroneous :^)
Hello Ricardo!
Thank you so much for this awesome package π
I have been experimenting with Apollo V2 client recently. But i ran into this very odd behavior.
When using apollo's inmomory cache, direct calls to query() or mutate() from the apollo client do not cause data from different types of queries/mutations to overwrite each other in the cache.
But when using the redux cache, the most recent query/mutation overwrites the apollo reducer in the redux store.
is this behavior is normal/expected? or could it be a bug resulting from my setup? In the meantime, I'll continue experimenting with different middleware/setups to find out more information.
code samples:
App.js
...
const store = configureStore(initialState, history);
const cache = new ReduxCache({ store });
const client = new ApolloClient({
uri: "/graphql",
cache
});
client
.mutate({
mutation: gql`
mutation {
insertUser (items:{fullName:"full name", email:"[email protected]", password:"testTest"})
}
`
})
.then(result => console.log(result));
client
.query({
query: gql`
{
homePosts {
_id
order
image
title
content
}
}
`
})
.then(result => console.log(result));
client
.query({
query: gql`
{
aboutPosts {
_id
order
image
title
content
}
}
`
})
.then(result => console.log(result));
configureStore.js
import { createStore, applyMiddleware, compose } from 'redux';
import { fromJS } from 'immutable';
import { routerMiddleware } from 'react-router-redux';
import createSagaMiddleware from 'redux-saga';
import createReducer from './reducers';
const sagaMiddleware = createSagaMiddleware();
export default function configureStore(initialState = {}, history) {
// Create the store with two middlewares
// 1. sagaMiddleware: Makes redux-sagas work
// 2. routerMiddleware: Syncs the location/URL path to the state
const middlewares = [sagaMiddleware, routerMiddleware(history)];
const enhancers = [applyMiddleware(...middlewares)];
// If Redux DevTools Extension is installed use it, otherwise use Redux compose
/* eslint-disable no-underscore-dangle, indent */
const composeEnhancers =
process.env.NODE_ENV !== 'production' &&
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// TODO Try to remove when `react-router-redux` is out of beta, LOCATION_CHANGE should not be fired more than once after hot reloading
// Prevent recomputing reducers for `replaceReducer`
shouldHotReload: false,
})
: compose;
/* eslint-enable */
const store = createStore(
createReducer(),
fromJS(initialState),
composeEnhancers(...enhancers),
);
// Extensions
store.runSaga = sagaMiddleware.run;
store.injectedReducers = {}; // Reducer registry
store.injectedSagas = {}; // Saga registry
// Make reducers hot reloadable, see http://mxs.is/googmo
/* istanbul ignore next */
if (module.hot) {
module.hot.accept('./reducers', () => {
store.replaceReducer(createReducer(store.injectedReducers));
});
}
return store;
}
reducers.js
import { apolloReducer } from 'apollo-cache-redux';
import { combineReducers } from 'redux-immutable';
import { fromJS } from 'immutable';
import { LOCATION_CHANGE } from 'react-router-redux';
/*
* routeReducer
*
* The reducer merges route location changes into our immutable state.
* The change is necessitated by moving to react-router-redux@4
*
*/
// Initial routing state
const routeInitialState = fromJS({
location: null,
});
/**
* Merge route into the global application state
*/
export function routeReducer(state = routeInitialState, action) {
switch (action.type) {
/* istanbul ignore next */
case LOCATION_CHANGE:
return state.merge({
location: action.payload,
});
default:
return state;
}
}
/**
* Creates the main reducer with the dynamically injected ones
*/
export default function createReducer(injectedReducers) {
return combineReducers({
route: routeReducer,
apollo: apolloReducer,
...injectedReducers,
});
}
results:
when using inMemory cache (all data is there):
How to dispatch apollo store clear? Like on user logout.
I can create my own action to clear it but it's probably not the better way.
Regards,
I'm currently trying to upgrade our Apollo 1.x app, which has a bunch of non-apollo redux requirements to Apollo 2.x so this project filled me with hope, but I'm having some issues which I think may be because we use redux-immutable
.
It seems that every graphql(MY_QUERY)(MyComponent)
HOC we create never actually receives the query result in props.data
.
My problem may well be elsewhere, but do you know if our use of redux-immutable
along with your module is likely/known to cause problems?
Thanks,
Paul.
Hello @rportugal Thanks for your efforts with this package! I have a couple of questions and I am really looking forward to get some answers here.
Basically my question is: Apart from having a different cache implementation for Apollo Client itself, how does the (Redux) usage vary in contrast to using Redux next to Apollo Client without this package?
First I implemented a minimal project by using Apollo Client and Redux side by side. The setup can be found in the src/index.js and the usage in the src/App.js. Next I refactored it to using this package. Only the setup changes in the src/index.js fole and the state layer is one more level deeply nested because of combineReducer
in the mapStateToProps
function (in src/App.js), but apart from this nothing changes.
Maybe I don't really understand the intention of the package, because I have never used Apollo Client 1.x where Redux was the default cache implementation. So I would love if someone could help me out here :) Perhaps the usage in the src/App.js is correct as it is, but something else changes that I am not aware of when using Redux as underlying cache.
The other thing which isn't clear to me is whether there would be something different in the usage of Redux in the src/App.js file when using this package (apart from having access to the Apollo Client instance in mapStateToProps
and mapDispatchToProps
).
Even though the Redux store instance is used in the Apollo Cache instance (and I guess should be implicitly) accessible due to React's Context API, you still need to use the Provider component from react-redux
next to the ApolloProvider.
Thank you for your time! At the moment I am trying to grasp how to connect Redux and Apollo Client, because lots of people are confused about it. So I try to getter a better understanding about it. Maybe it helps that I ended up trying this package because of this issue apollographql/apollo-client#2593
Hello.
Can I currently use this package in production environments?
Has it been "exhaustively" tested already?
Thanks π
https://github.com/rportugal/apollo-cache-redux/blob/0.1.0-alpha.7/src/reduxCache.ts#L22 is always passing an empty object as the first parameter. I think it should be passing config.store. Currently it always overwrites my initial state with an empty object and messes with my server side rendering.
If I am using a mutation to authenticate users is there any way to hide the password being sent?
If the store
option is not passed to the ReduxCache
constructor, it will create and manage a Redux store automatically. However, it doesn't allow middleware to be set up. ReduxCache
constructor needs a middleware
option.
@rportugal thanks for you contribution!
What about performance for write and read on apollo-cache-redux
VS. the built-in cache?
Are there any disadvantage if you use apollo-cache-redux
?
Does anybody have some experience?
any tips on how to incorporate this with an immutable js store? would I want to replace all write operations with a fromJS
wrapper?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.