I was trying to react query for the first time then I got this at the start of my React app.
import React from 'react'
import { useQuery } from "react-query";
const fetchPanets = async () => {
const result = await fetch('https://swapi.dev/api/people')
return result.json()
}
const Planets = () => {
const { data, status } = useQuery('Planets', fetchPanets)
console.log("data", data, "status", status)
return (
<div>
<h2>Planets</h2>
</div>
)
}
export default Planets
As the error suggests, you need to wrap your application in a QueryClientProvider. This is on the first page of the docs:
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
While this is most commonly caused by not having your application wrapped in a <QueryClientProvider>, in my case it happened because I was importing some shared components, which ended up with a different context. You can fix this by setting the contextSharing option to true
That would look like:
import { QueryClient, QueryClientProvider } from 'react-query'
const queryClient = new QueryClient()
function App() {
return <QueryClientProvider client={queryClient} contextSharing={true}>...</QueryClientProvider>
}
From the docs: (https://react-query.tanstack.com/reference/QueryClientProvider)
contextSharing: boolean (defaults to false)
Set this to true to enable context sharing, which will share the first and at least one instance of the context across the window to ensure that if React Query is used across different bundles or microfrontends they will all use the same instance of context, regardless of module scoping.
Just make changes like below it will work fine
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
ReactDOM.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
document.getElementById('root')
);
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
const queryClient = new QueryClient();
const fetchPanets = async () => {
const result = await fetch('https://swapi.dev/api/people')
return result.json()
}
const Planets = () => {
const { data, status } = useQuery('Planets', fetchPanets)
console.log("data", data, "status", status)
return (
<div>
<h2>Planets</h2>
</div>
);
}
export default function Wraped(){
return(<QueryClientProvider client={queryClient}>
<Planets/>
</QueryClientProvider>
);
}
Single SPA (micro-frontend) - React Query v3.34.15
I was getting this error while trying to integrate a sigle-spa react parcel into the root application.
I used craco-plugin-single-spa-application for the building of a CRA app as a way to adapt it for a parcel. In the entry config I was pointing to my single-spa-react config.
// craco.config.js
const singleSpaApplicationPlugin = require('craco-plugin-single-spa-application')
module.exports = {
plugins: [
{
plugin: singleSpaApplicationPlugin,
options: {
orgName: 'uh-platform',
projectName: 'hosting',
entry: 'src/config/single-spa-index.cf.js',
orgPackagesAsExternal: false,
reactPackagesAsExternal: true,
externals: [],
minimize: false
}
}
]
}
In the single-spa-index.cf.js file I had the following configs.
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import App from '../App'
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
errorBoundary() {
return <div>Ocorreu um erro desconhecido!</div>
}
})
export const { bootstrap, mount, unmount } = lifecycles
After reading a bunch of forums and the react-query documentation, the only thing that I figured out I needed to change was pass in the QueryClientProvider the prop contextSharing as true. After had did this change, ran the building and access the route that opens my parcel. I got the same error.
import React from 'react'
import ReactDOM from 'react-dom'
import { QueryClient, QueryClientProvider } from 'react-query'
import { ReactQueryDevtools } from 'react-query/devtools'
import App from './App'
const queryClient = new QueryClient()
const isDevelopmentEnv = process.env.NODE_ENV === 'development'
if (isDevelopmentEnv) {
import('./config/msw/worker').then(({ worker }) => worker.start())
}
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider contextSharing={true} client={queryClient}>
<App />
{isDevelopmentEnv && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>
</React.StrictMode>,
document.getElementById('root')
)
But, how do I solved that. Well, it was was simple. I couldn't even imagine why it was working locally. But not after building and integration.
The problem was because I put the React Query Provider inside the index o the application and in my single-spa-index.cf.js I was importing import App from '../App' which really wasn't wrapped by the provider. Once I also was importing App in the application index, where It was wrapped making It works locally. 😢😢
So after figure that out, my code was like that:
CODE AFTER SOLUTION
// craco.config.js
const singleSpaApplicationPlugin = require('craco-plugin-single-spa-application')
module.exports = {
plugins: [
{
plugin: singleSpaApplicationPlugin,
options: {
orgName: 'uh-platform',
projectName: 'hosting',
entry: 'src/config/single-spa-index.cf.js',
orgPackagesAsExternal: false,
reactPackagesAsExternal: true,
externals: [],
minimize: false
}
}
]
}
// src/config/single-spa-index.cf.js
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import App from '../App'
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
errorBoundary() {
return <div>Ocorreu um erro desconhecido!</div>
}
})
export const { bootstrap, mount, unmount } = lifecycles
// App.tsx
import { QueryClient, QueryClientProvider } from 'react-query'
import { ReactQueryDevtools } from 'react-query/devtools'
import { config } from 'config/react-query'
import Routes from 'routes'
import GlobalStyles from 'styles/global'
import * as S from './styles/shared'
const queryClient = new QueryClient(config)
const isDevelopmentEnv = process.env.NODE_ENV === 'development'
if (isDevelopmentEnv) {
import('./config/msw/worker').then(({ worker }) => worker.start())
}
function App() {
return (
<QueryClientProvider contextSharing={true} client={queryClient}>
<S.PanelWrapper>
<Routes />
<GlobalStyles />
</S.PanelWrapper>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
export default App
// index.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
document.getElementById('root')
)
Well, it was long but I hope it helps someone that's undergoing for the same problem as mine. 🙌🙌🙌
I was trying to fix the same thing:
I followed the React Query docs
and used the concept of Higher Order Component
See if it helps:
import React from 'react';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
import Planet from './Planet';
const queryClient = new QueryClient();
const fetchPlanets = async () => {
const res = await fetch('http://swapi.dev/api/planets/');
return res.json();
}
const Planets = () => {
const { data, status } = useQuery('planets', fetchPlanets);
return (
<div>
<h2>Planets</h2>
{ status === 'loading' && (<div>Loading data...</div>)}
{ status === 'error' && (<div>Error fetching data</div>)}
{
status === 'success' && (
data.results.map(planet =>
<Planet
key={planet.name}
planet={planet}
/>
)
)
}
</div>
)
}
// Higher order function
const hof = (WrappedComponent) => {
// Its job is to return a react component warpping the baby component
return (props) => (
<QueryClientProvider client={queryClient}>
<WrappedComponent {...props} />
</QueryClientProvider>
);
};
export default hof(Planets);
In my case I was importtng from 'react-query' in one place and '#tanstack/react-query' in another.
I got that error when trying to add the react-query devtools.
The problem was I was installing it wrongly according my version, I was using react-query v3.
WRONG FOR react-query V3 (GOOD FOR V4)
import { ReactQueryDevtools } from '#tanstack/react-query-devtools';
OK FOR react-query V3
import { ReactQueryDevtools } from 'react-query/devtools';
In my case I accidentally used two different versions of react-query in my modules.
In my case
Error import { QueryClient, QueryClientProvider } from "#tanstack/react-query";
Solution import { QueryClient, QueryClientProvider } from "react-query";
remove it #tanstack/
Just be careful when upgrade from react-query v3 to #tanstack/react-query v4.
Ensure that you replace all imports as "react-query" to "#tanstack/react-query" and then run yarn remove the lib that you won't use anymore, otherwise you may accidentally import the unexpected one.
This happened to me and caused this error.
Related
I'm pretty confident this is due to the RTL render not being used, but I'm not sure where the render should go given I apparently have to use ReactDOM.react. At least it was needed to resolve one 4-5 errors I got along the way.
App and test code...
// App.jsx
import React from 'react';
import { Provider } from 'react-redux';
import { compose } from 'redux';
import { Switch, Route } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import Authentication from './Authentication';
import configureStore, { history } from '../services/history';
const App = () => {
const protectedRoute = compose(Timers, RequireAuth);
const store = configureStore();
return (
<div data-testid='App'>
<Provider store={store}>
<ConnectedRouter history={history}>
<Switch>
<Route exact path='/' component={Authentication} />
</Switch>
</div>
</ConnectedRouter>
</Provider>
</div>
);
};
export default App;
// Authentication.jsx
import React, { Component } from 'react';
export default class Authentication extends Component {
render() {
return (
<div data-testid='Authentication' id='auth'>
...
</div>
);
}
}
Started out with this test:
// Authentication.test.jsx
import React from 'react';
import { render, screen } from '#testing-library/react';
import Authentication from './Authentication';
test('authentication page renders', () => {
render(<Authentication />);
const auth = screen.getByTestId('Authentication');
expect(auth).toBeInTheDocument();
});
Which resulted in:
Error: Uncaught [Error: Could not find "store" in the context of "Connect(Form(Connect(Signin)))". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(Form(Connect(Signin))) in connect options.]
Addressing this issue, and 4-5 other subsequent errors, has resulted in the following:
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { render, screen } from '#testing-library/react';
import '#testing-library/jest-dom';
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';
import Authentication from './Authentication';
import { MemoryRouter } from 'react-router-dom';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const store = mockStore({
auth: {
authenticated: true,
},
});
test('authentication page renders', () => {
const div = document.createElement('div');
ReactDOM.render(
<Provider store={store}>
<MemoryRouter>
<Authentication />
</MemoryRouter>
</Provider>,
div
);
const authentication = screen.queryByTestId('Authentication');
expect(authentication).toBeInTheDocument();
});
Which results in:
received value must be an HTMLElement or an SVGElement.
Received has value: null
28 | );
29 | const authentication = screen.queryByTestId('Authentication');
> 30 | expect(authentication).toBeInTheDocument();
| ^
31 | });
32 |
Again, pretty sure this is from not using RTLs render. Not sure where it should go and adding it creates the first error I had so I'm going in circles.
Any suggestions?
If it is helpful I could retrace all my previous steps and post the various error messages which led me to this point.
Well, somewhere along the line of addressing the various error messages that came up, one fix was adding ReactDOM.render()... thought it was necessary, turns out it was not.
This is sufficient and works:
import React from 'react';
import { Provider } from 'react-redux';
import { render, screen } from '#testing-library/react';
import thunk from 'redux-thunk';
import configureMockStore from 'redux-mock-store';
import { MemoryRouter } from 'react-router-dom';
import '#testing-library/jest-dom';
import Authentication from './Authentication';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const store = mockStore({
auth: {
authenticated: true,
},
});
test('authentication page renders', () => {
render(
<Provider store={store}>
<MemoryRouter>
<Authentication />
</MemoryRouter>
</Provider>
);
const authentication = screen.getByTestId('Authentication');
expect(authentication).toBeInTheDocument();
});
I am using the following Component with Meteor
https://github.com/CaptainN/npdev-react-loadable
import { Loadable } from 'meteor/npdev:react-loadable';
I create my Loadable component as follows
const HomePageBlog = Loadable({
loading: () => <FullPageLoader />,
loader: () => import('./HomePageBlog'),
});
I have gone through the SSR setup in the docs and it looks something like this
Server index.js
import React from 'react';
import { renderToString, renderToNodeStream } from 'react-dom/server';
import { onPageLoad } from 'meteor/server-render';
import { StaticRouter } from 'react-router';
import { Helmet } from 'react-helmet';
import Loadable from 'react-loadable';
import { ServerStyleSheet } from 'styled-components';
import {
LoadableCaptureProvider,
preloadAllLoadables,
} from 'meteor/npdev:react-loadable';
preloadAllLoadables().then(() => {
onPageLoad(async (sink) => {
const context = {};
const sheet = new ServerStyleSheet();
const loadableHandle = {};
const routes = (await import('../both/routes.js')).default;
const App = (props) => (
<StaticRouter location={props.location} context={context}>
{routes}
</StaticRouter>
);
const modules = [];
// const html = renderToNodeStream((
const html = renderToString(
<LoadableCaptureProvider handle={loadableHandle}>
<App location={sink.request.url} />
</LoadableCaptureProvider>,
);
// we have a list of modules here, hopefully Meteor will allow to add them to bundle
// console.log(modules);
sink.renderIntoElementById('app', html);
sink.appendToBody(loadableHandle.toScriptTag());
const helmet = Helmet.renderStatic();
// console.log(helmet);
sink.appendToHead(helmet.meta.toString());
sink.appendToHead(helmet.title.toString());
sink.appendToHead(helmet.link.toString());
sink.appendToHead(sheet.getStyleTags());
});
});
client index.js
import { Meteor } from 'meteor/meteor';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, withRouter } from 'react-router-dom';
import { onPageLoad } from 'meteor/server-render';
import { createBrowserHistory } from 'history';
import { preloadLoadables } from 'meteor/npdev:react-loadable';
console.log('hi');
const history = createBrowserHistory();
/**
* If browser back button was used, flush cache
* This ensures that user will always see an accurate, up-to-date view based on their state
* https://stackoverflow.com/questions/8788802/prevent-safari-loading-from-cache-when-back-button-is-clicked
*/
(function () {
window.onpageshow = function (event) {
if (event.persisted) {
window.location.reload();
}
};
})();
onPageLoad(async () => {
const routes = (await import('../both/routes.js')).default;
const App = () => (
<>
<Router history={history}>
<div>{routes}</div>
</Router>
</>
);
preloadLoadables().then(() => {
ReactDOM.hydrate(<App />, document.getElementById('app'));
});
});
What I am trying to determine is what exactly react loadable does. I am wanting to separate my bundle so I can only load code via SSR when it is needed. Right now I have quite a low score on lighthouse for page speed.
The code that I have here works.
But what I expected to happen was have a separate request to grab more js for the loadable component when it is requested. So it's not in the initial bundle. Is this not how this package works.
Could someone one help me me understand this better.
Thanks for any help ahead of time
Here is an Error:
Objects are not valid as a React child (found: object with keys {$$typeof, type, compare, WrappedComponent}). If you meant to render a collection of children, use an array instead.
It works just fine if I don't use connect in main.js and using connect in App.js doesn't make an Error, but once I use connect in main.js it throws me this error. What do I do wrong? And I'm using connect same way as in App.js Thank you
Here is sandBox https://codesandbox.io/s/busy-euler-7mpi7?file=/src/main.js
you can experience, just delete connect in main.js and it will start working
App.js
import React, { useEffect } from "react";
import './styles/main.scss';
import './App.scss';
import routes from "./router/router";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { connect } from "react-redux";
import {checkUser, fetchUsers, fetchPolls} from "./store/index";
function App (props) {
useEffect(() => {
let { loadUsers} = props
loadUsers();
}, [])
let jsxRoutes = routes.map(el =>
<Route
path={el.url}
exact={el.exact}
key={el.url}>
{ el.component }
</Route>
)
return (
<Router>
<div className="App">
<Switch>
{ jsxRoutes }
</Switch>
</div>
</Router>
);
}
const mapStateToProps = state => {
return {
users: state.users.data,
}
}
const mapDispatchToProps = dispatch => {
return {
loadUsers: () => dispatch(fetchUsers())
}
}
export default connect(mapStateToProps, mapDispatchToProps)(App);
Main.js
import React from "react";
import "./main.scss"
import { connect } from "react-redux"
const Main = (props) => {
return(
<main>
main pg
</main>
)
}
export default connect(null, null)(Main);
In App.js try this instead:
let jsxRoutes = routes.map((el) => (
<Route path={el.url} exact={el.exact} key={el.url} component={el.component} />
));
Or the shorter version: <Route {...el} />
We are currently struggling using Apollo Client to manage local state in a react application. We were able to build up a very simple example where we just display a div depending on the result of a mutation. The effect of the mutation should only be to display an alert message and return nothing.
We have come up with the following very simple example code:
File index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { ApolloClient } from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { withClientState } from 'apollo-link-state';
import App from './App';
const resolvers = {
Mutation: {
setData: (_, {myBool}) => {
alert(myBool);
return null;
}
}
};
const client = new ApolloClient({
cache: new InMemoryCache(),
link: withClientState({ resolvers })
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById('root')
);
File App.js:
import React, { Component, Fragment } from 'react';
import gql from 'graphql-tag';
import { Mutation } from 'react-apollo';
class App extends Component {
setData = () => {
alert('setData is called');
const SET_DATA = gql`
mutation SetData($myBool: Boolean!) {
setData(myBool: $myBool) #client
}
`;
return (
<Mutation mutation={SET_DATA} variables={{ myBool: true }}>
{(_, { loading, error }) => (
<div>
{loading && <p>...loading...</p>}
{error && <p>ERROR ! Try reloading.</p>}
</div>
)}
</Mutation>
);
};
render() {
return (
<Fragment>
<h1>App</h1>
{this.setData()}
</Fragment>
);
}
}
export default App;
Could someone please tell us why the alert method we call in the setData() resolver (from file index.js) isn't called upon page loading?
Hi I'm new to Expo but I've been having a hard time trying to run my code. I'm stuck at having the error: You must specify initialRoute or initialStack to initialize this StackNavigation even though I already set it up.
Here's my main.js
import Expo from 'expo'
import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import {
NavigationProvider,
StackNavigation,
} from '#expo/ex-navigation'
import RootReducer from './src/reducers'
import Router from './src/navigation/Router'
const store = createStore(RootReducer)
const App = () => (
<Provider store={store}>
<NavigationProvider router={Router}>
<StackNavigation intitialRoute={Router.getRoute('splash')} />
</NavigationProvider>
</Provider>
)
Expo.registerRootComponent(App)
Here's my Router.js
import { createRouter } from '#expo/ex-navigation'
// Screens
import SplashScreen from '../screens/SplashScreen'
import LoginScreen from '../screens/LoginScreen'
const Router = createRouter(() => ({
splash: () => SplashScreen,
login: () => LoginScreen,
}))
export default Router
What seems to be the problem at my setup? I just followed the example on ExNavigation.
Here's my example on Sketch but can't make it run but will leave the link for the full code.
You have a typo in the prop's name in this part of the code
<StackNavigation intitialRoute={Router.getRoute('splash')} />
It is initialRoute instead of intitialRoute.