I am installing react-native-paper in my existing expo app, and wanted to follow this guide to have a PaperProvider: https://callstack.github.io/react-native-paper/theming.html#applying-a-theme-to-the-whole-app
This is what is recommended :
import * as React from 'react';
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import App from './src/App';
const theme = {
...DefaultTheme,
roundness: 2,
colors: {
...DefaultTheme.colors,
primary: '#3498db',
accent: '#f1c40f',
},
};
export default function Main() {
return (
<PaperProvider theme={theme}>
<App />
</PaperProvider>
);
As soon as I add in my tree the <PaperProvider />, I am not able to test my <App />:
My test look like this:
import HomeView from '../index.js';
import { render } from '../../../../testUtils/viewUtils';
describe('<HomeView />', () => {
it('should render HomeView', async (done) => {
const tree = await render([
{
page: 'home',
message: 'Home',
path: '/',
component: HomeView,
exact: true,
},
{
page: 'list',
message: 'List',
path: '/list',
component: HomeView,
exact: true,
},
]);
expect(tree.root.findByProps({ name: 'version' }).props.name).toEqual('version');
expect(tree.toJSON().children.length).toEqual(2);
done();
});
});
With my test util that look like viewUtils.js:
import React from 'react';
import renderer from 'react-test-renderer';
import { AppCore } from '../core/AppCore';
import { getEnvVars } from '../config';
import history from '../store/history';
import theme from '../theme';
import { en, fr } from '../translation';
import customReducers from '../store/reducer';
export async function render(routes) {
const TestComponent = withApp(routes);
const tree = renderer.create(
<TestComponent />,
);
// next line will solve the async init with <PersistGate /> (redux-persist);
await new Promise((resolve) => setTimeout(resolve, 1));
return tree;
}
export function withApp(routes) {
return () => (
<AppCore
translations={{
fr,
en,
}}
theme={theme}
routes={routes}
version="1.0.0"
env={getEnvVars()}
history={history}
customReducers={customReducers}
userPersistConfig={{
blacklist: [
'router',
'theme',
],
}}
/>
);
}
and my AppCore that look like:
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import '@expo/match-media';
import AppContextProvider from '@yeutech/app-context';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { AppearanceProvider } from 'react-native-appearance';
import { Provider as PaperProvider, DefaultTheme } from 'react-native-paper';
import ActivityIndicator from './ActivityIndicator';
import SplashScreenCore from './SplashScreenCore';
import configureStore from './init/configureStore';
import configureI18n from './init/configureI18n';
import configureNavigation from './init/configureNavigation';
/* eslint-disable react/no-unescaped-entities, react/jsx-one-expression-per-line */
export function AppCore(props) {
const {
splash,
routes,
version,
env,
translations,
customReducers,
initialState,
history,
loadingComponent,
userPersistConfig,
} = props;
const SplashScreen = splash ? (splashProps) => <SplashScreenCore {...splashProps} {...splash} /> : Fragment;
const { AppContainer, pages, routesMap } = configureNavigation(routes, history);
const localizationContext = configureI18n(translations);
const { store, persistor } = configureStore(customReducers, initialState, userPersistConfig, history);
return (
<AppContextProvider
pages={pages}
routesMap={routesMap}
env={env}
version={version}
loadingComponent={loadingComponent}
{...localizationContext}
>
<Provider store={store}>
<PersistGate
persistor={persistor}
loading={null}
>
<PaperProvider theme={DefaultTheme}>
<SplashScreen>
<AppContainer />
</SplashScreen>
</PaperProvider>
</PersistGate>
</Provider>
</AppContextProvider>
);
}
AppCore.propTypes = {
/** list of all application routes */
routes: PropTypes.array.isRequired,
/** Application version */
version: PropTypes.string.isRequired,
/** Application environment configuration */
env: PropTypes.object,
/** props passed to the SplashScreenCore component */
splash: PropTypes.object,
/** a translation object, with local as key and object of messages as values */
translations: PropTypes.object,
/** customReducers will be passed to redux combineReducers */
customReducers: PropTypes.object,
/** redux initialState */
initialState: PropTypes.object,
/** react-router history navigation (for web) */
history: PropTypes.object,
/** the loading component injected into the application context */
loadingComponent: PropTypes.any,
/** it will passed to redux persist config */
userPersistConfig: PropTypes.object,
};
AppCore.defaultProps = {
env: {},
splash: null,
translations: {},
customReducers: {},
initialState: {},
history: null,
loadingComponent: ActivityIndicator,
userPersistConfig: {},
};
export default (props) => <AppearanceProvider><AppCore {...props} /></AppearanceProvider>;
Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Error:
Removing the <PaperProvider /> solve this error,
What am I configuring wrong?
I was able to solve it by adding one <PaperProvider /> per page, instead of one per application.