I am working on a RN app using react-native-paper to handle theming and UI. I have the theme working to format my components, however when I try to incorporate custom fonts it does not have any effect on the react-native-paper components. I have followed the [font guide][1] but it did not change this issue.
I follow the expo example of how to load fonts using loadFontAsync(), and when I pass these fonts to my own components using the style prop fontFamily: 'Rubik-Regular the font works so I know it is not an issue of the font not existing.
As I am new to react-native-paper, I think my issue is with my fontConfig or configureFonts(). Any help or direction would be greatly appreciated.
import React from 'react';
import { Provider as ReduxProvider } from 'react-redux'
import configureStore from './store'
]import { configureFonts, DefaultTheme, Provider as PaperProvider } from 'react-native-paper'
import { AppLoading } from 'expo';
import * as Font from 'expo-font';
import AppNavigator from './components/AppNavigator'
const store = configureStore();
const fontConfig = {
default: {
regular: {
fontFamily: 'Rubik-Regular',
fontWeight: 'normal',
},
medium: {
fontFamily: 'Rubik-Black',
fontWeight: 'normal',
},
light: {
fontFamily: 'Rubik-Light',
fontWeight: 'normal',
},
thin: {
fontFamily: 'Rubik-LightItalic',
fontWeight: 'normal',
},
},
};
let customFonts = {
'Rubik-Regular': require('./assets/fonts/Rubik-Regular.ttf'),
'Rubik-Black': require('./assets/fonts/Rubik-Black.ttf'),
'Rubik-Light': require('./assets/fonts/Rubik-Light.ttf'),
'Rubik-LightItalic': require('./assets/fonts/Rubik-LightItalic.ttf'),
}
const theme = {
...DefaultTheme,
roundness: 30,
fonts: configureFonts(fontConfig),
colors: {
...DefaultTheme.colors,
primary: '#0d80d6',
accent: '#E68FAE',
background: '#C6E1F2',
},
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
fontsLoaded: false,
};
}
async loadFontsAsync() {
await Font.loadAsync(customFonts);
this.setState({ fontsLoaded: true });
}
componentDidMount() {
this.loadFontsAsync();
}
render() {
if (this.state.fontsLoaded) {
return (
<ReduxProvider store={store}>
<PaperProvider theme={theme}>
<AppNavigator/>
</PaperProvider>
</ReduxProvider>
);
}
else {
return <AppLoading/>;
}
}
}
I am using react-native 0.63.3 and Expo.
I know this is from a while ago but I ran into the same problem today and found this related issue in their repository on GitHub: https://github.com/callstack/react-native-paper/issues/1502#issuecomment-576534682
TL;DR the solution is you have to specify fontConfig.ios and probably fontConfig.android for it to work, instead of just having fontConfig.default.
for your case, you can probably adapt to something like
const _fontConfig = {
regular: {
fontFamily: 'Rubik-Regular',
fontWeight: 'normal',
},
medium: {
fontFamily: 'Rubik-Black',
fontWeight: 'normal',
},
light: {
fontFamily: 'Rubik-Light',
fontWeight: 'normal',
},
thin: {
fontFamily: 'Rubik-LightItalic',
fontWeight: 'normal',
},
};
const fontConfig = {
ios: _fontConfig,
android: _fontConfig,
};
Related
I have created a customTheme file to extend the Chakra them and have created a custom component called card which I would like to have variants applicable, but for some reason the base styles show and the variants never work.
extendTheme.js
`
import { extendTheme } from '#chakra-ui/react';
import { ButtonStyles as Button } from './styles/components/ButtonStyles';
import { CardStyle as Card } from './styles/components/CardStyle';
const customTheme = extendTheme({
colors: {
brand: {
100: '#f7fafc',
900: '#f77070',
},
grey: {
100: '#eff3fa',
},
blue: {
100: '#0098ae',
},
red: {
100: '#ff3d3d',
200: '#f77070'
},
},
fonts: {
body: 'Graphik Font',
heading: 'Graphik Font',
},
fontWeights: {
hairline: 100,
thin: 200,
light: 300,
normal: 400,
medium: 500,
semibold: 600,
bold: 700,
extrabold: 800,
black: 900,
},
components: {
Button,
Card,
}
});
export default customTheme;
`
cardStyle.js
`
import { defineStyleConfig } from '#chakra-ui/react'
export const CardStyle = defineStyleConfig({
// The styles all Cards have in common
baseStyle: {
display: 'flex',
flexDirection: 'column',
background: 'white',
alignItems: 'center',
gap: 6,
},
// Two variants: rounded and smooth
variants: {
rounded: {
padding: 8,
borderRadius: 'xl',
boxShadow: 'xl',
},
smooth: {
padding: 6,
borderRadius: 'base',
boxShadow: 'md',
},
},
// The default variant value
defaultProps: {
variant: 'smooth',
},
})
`
Card.jsx
`
import { Box, useStyleConfig } from '#chakra-ui/react'
function CardTest(props) {
const { variant, ...rest } = props
const styles = useStyleConfig('Card', { variant })
// Pass the computed styles into the `__css` prop
return <Box __css={styles} {...rest} />
}
export default CardTest
`
including the card in another jsx
`
<CardTest variant='rounded'>
<Image
src={imageOne}
rounded='full'
w={32}
h={32}
boxShadow='md'
/>
<Heading mt={6} maxW={60} size='lg' textAlign='center' color='gray.700'>
Explore the outdoors
</Heading>
<Text mt={6} mb={6} size='sm' color='brand.900'>
some text in the card
</Text>
<Image src={imageOne} w={32} h={32} />
</CardTest>
`
import React from 'react';
import ReactDOM from "react-dom/client";
import { ChakraProvider } from '#chakra-ui/react';
import customTheme from './extendTheme';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<ChakraProvider theme={customTheme}>
<App />
</ChakraProvider>
</React.StrictMode>,
);
it uses the example off of the chakra docs but for some reason the variant never changes and I cannot see why when if i tell it o use Button as styles and not Card the variants work for button.
Aha! You're mapping CardStyles to Card, but actually rendering CardTest!
import { CardStyle } from './styles/components/CardStyle';
const customTheme = extendTheme({
// ...
components: {
Button,
Card: CardStyle, // targets Card component...
CardTest: CardStyle, // ...but you're rendering CardTest
}
});
Here's a working version, slightly simplified:
https://codesandbox.io/s/so-74816092-oio6qr?file=/src/index.js
Side note, CardStyle can't apply to Card, as it's a multipart component:
https://chakra-ui.com/docs/styled-system/component-style#single-part-and-multipart-components
https://chakra-ui.com/docs/styled-system/advanced-theming
https://chakra-ui.com/docs/components/card/theming
Outdated
You haven't included a snippet showing where you provide your custom theme to Chakra's ThemeProvider, so this may explain your issue:
// extendTheme.js
import { extendTheme } from "#chakra-ui/react"
const theme = extendTheme({
// ...
})
export default theme
import * as React from 'react'
import { ChakraProvider } from '#chakra-ui/react'
import theme from './extendTheme.js'
function App() {
// Wrap ChakraProvider at the root of your app
return (
<ChakraProvider theme={theme}>
<App />
</ChakraProvider>
)
}
// Now you can use these colors in your components
function Usage() {
return <Box bg="brand.100">Welcome</Box>
}
https://chakra-ui.com/docs/styled-system/customize-theme
I an using yarn workspaces, and i have 3 packages: app, electron app using react, and shared for all the common stuff. When importing shared in the app or electron, it says that error in vscode:
error
i dont know what to do :/ i tried everything. and the files arent ts, but js.
import { View, StyleSheet, Text } from 'react-native';
import Header from 'shared/components/Header';
//const socket = new Socket("192.168.1.146", 8080, "http");
(async () => {
//await socket.connect();
})();
const styles = StyleSheet.create({
screenContainer: {
flex: 1
},
text: {
fontSize: 20,
color: 'cornflowerblue',
marginTop: 50,
alignSelf: 'center'
}
});
const App = () => {
/*useEffect(() => {
if (socket.getSocket() != undefined && socket.getSocket().connected) {
socket.getSocket().disconnect();
}
});*/
return (
<View styles={styles.screenContainer}>
<Header />
<Text style={styles.text}>I'm a React Native component</Text>
</View>
);
};
export default App;
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
header: {
paddingTop: 50,
backgroundColor: 'red'
},
headerText: {
fontSize: 22,
color: 'white',
fontWeight: 'bold',
paddingHorizontal: 10
}
});
const Header = () => {
return (
<View style={styles.header}>
<Text style={styles.headerText}>I'm a shared component.</Text>
</View>
);
};
export default Header;
create fallback.d.ts with content:
declare module '*';
And include it in your tsconfig.json https://www.typescriptlang.org/tsconfig#include (path to d.ts file relative to tsconfig.json path)
{
"include": ["./fallback.d.ts", ...],
...
}
This will allow you to import from js files.
But imho better would be to convert Header.js file to typescript
I'm making a tricky nav component using MUI Persistent Drawers with a React + Next structure. In order to get the content shrinking thanks to the state change, I had to put the whole navigation system inside of the _app.js file instead of having it in a distinct component.
Even though it clearly works, I wonder if it'll not impact rendering and performance once built. The makeStyles((theme) seems to work just fine but is not highlighted in VScode, probably because I used both of makeStyles, useTheme and ThemeProvider in the same file, as below :
import { makeStyles, useTheme } from '#material-ui/core/styles';
import { ThemeProvider } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({ ...
(className example:) appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(['margin', 'width'], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
}, ... etc
Was it a good idea to put it all together in _app.js, or do I need to refactor everything into a new component passing props to parent somehow ?
Thanks for considering, best regards to all of you
I recommend you to put your theme inside a folder theme/theme.js and use createMuiTheme then in your app.js wrap your whole component with the theme provider ! That would spread your theme across the app and let you use it where you want ! Is the convention we got with material-ui.
theme/theme.js:
import { createMuiTheme } from "#material-ui/core/styles"
export const themeObject = {
palette: {
primary: { main: "#333333" },
secondary: { main: "#FD8C7C" },
},
backgroundColor: {
primary: { main: "#FEF8F8" },
secondary: { main: "#FFFFFF" },
},
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 960,
lg: 1280,
xl: 1920,
},
},
overrides: {
MuiDivider: {
root: {
backgroundColor: "#FFFFFF",
},
},
},
}
export default createMuiTheme(themeObject)
pages/app,js:
import React from "react"
import { ThemeProvider } from "#material-ui/styles"
import Box from "#material-ui/core/Box"
import defaultTheme from "../theme/theme"
const App = () => {
return (
<Box>
<ThemeProvider theme={defaultTheme}>
...
</ThemeProvider>
</Box>
)
}
export default App
component/SideBar.js:
import React from "react"
import { makeStyles } from "#material-ui/core/styles"
const useStyles = makeStyles((theme) => ({
drawer: {
width: theme.sidebar.width,
color: theme.palette.primary
flexShrink: 0,
whiteSpace: "nowrap",
"& .MuiDrawer-paper": {
top: "unset",
},
},
drawerClose: {
transition: theme.transitions.create("width", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
overflowX: "hidden",
width: theme.spacing(7) + 1,
[theme.breakpoints.up("sm")]: {
width: theme.spacing(7) + 1,
},
},
expandButton: {
[theme.breakpoints.up("sm")]: {
marginLeft: theme.spacing(-2.5),
marginRight: theme.spacing(2.5),
},
},
}))
export default function Sidebar(props) {
const classes = UseStyles()
return (...)
}
In the SideBar you can see that i have use the theme.zindex.drawer who come from directly theme.js.
I also recommend you to go check this MUI THEMING that would let you dive into the theming more deeply !
I want to make an app that makes a compass and compass should changes with changing direction of magnetometer. The code attached below shows a strange error. Although I have run npm install react-timer-mixin to sort the problem.By running this code on Expo it shows an error like
Super expression must either be a null or a function.
import React, {Components} from 'react';
import {Image, ImageBackground, View, Text, StyleSheet} from 'react-native';
import Expo from 'expo';
export default class App extends Components{
state={
isReady: false,
v: null,
};
_setMagnetometerAsync = async() =>{
Expo.Magnetometer.addListener((v)=>{
this.setState({v});
});
}
componentDidMount() {
this._setupMagnetometerAsync();
}
render(){
return(
<View style = {styles.container}>
<Text>{JSON.stringify(this.state.v)}</Text>
<ImageBackground
source = {require('./compassFace.png')}
style = {{
height: 320,
width: 320,
paddingTop:Expo.Constants.statusBarHeight,
alignItems: 'center',
justifyContents: 'center',
}}>
<Image
source = {require('./CompassNeedle.png')}
style={{
height: 420,
width: 420,
opacity: 0.65,
}}
/>
</ImageBackground>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#ecf0f1',
},
paragraph:{
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
});
Some fixes:
1.
import React, {Components} from 'react';
to
import * as React from 'react';
2.
componentDidMount(){
this._setupMagnetometerAsync();
}
to
componentDidMount(){
this._setMagnetometerAsync();
}
3.
export default class App extends Components{
to
export default class App extends React.Component{
when I test App.js I have the following error that appears:
TypeError: Cannot read property 'createStackNavigator' of undefined
24 | borderBottomWidth:0,
25 | },
> 26 | headerTintColor: '#294c95',
| ^
27 | headerTitleStyle: {
28 | fontWeight: 'bold',
29 | color:'white',
the file that indicates, it is HomeNavigation.js. On the other hand the line that indicates is correct and in this file the code is correct
here is my test
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import renderer from 'react-test-renderer';
global.fetch = jest.fn(() => new Promise(resolve => resolve()));
jest.mock('react-native-gesture-handler', () => {});
jest.mock('react-navigation-stack', () => { BaseButton: {} });
//jest.mock('react-navigation', ()=>{}); //if I add or remove this line it doesn't change anything.
describe('App', ()=> {
it('renders correctly the App component', () => {
const tree = renderer.create(<App/>).toJSON();
expect(tree).toMatchSnapshot();
});
});
jest.mock('react-native-gesture-handler', () => {}) this line solves this problem: TypeError: Cannot read property 'State' of undefined
jest.mock('react-navigation-stack', () => { BaseButton: {} }); this line solves this problem: TypeError: Cannot read property 'BaseButton' of undefined
HomeNavigation.js
import React from "react";
import {createStackNavigator} from "react-navigation";
import {Screen1Screen} from "../Screen"; //whatever name
import {Icon} from "react-native-elements";
import {fromRight} from 'react-navigation-transitions';
import {CLR_MENU} from "../assets/styles/colors";
export const HomeNavigation = createStackNavigator({
Screen1: Screen1Screen // whatever name // this part is correct
},{
cardStyle: {
backgroundColor: 'black',
opacity: 1,
},
defaultNavigationOptions: (navigation) =>({
headerStyle: {
backgroundColor: [CLR_MENU],
borderBottomWidth:0,
},
headerTintColor: '#294c95', // the error point on this line
headerTitleStyle: {
fontWeight: 'bold',
color:'white',
},
headerRight:
<Icon
name = "menu"
size = {24}
color = "white"
onPress={_=>navigation.navigation.openDrawer()}
containerStyle={{marginRight:10}}
underlayColor={CLR_MENU}
/>,
}),
transitionConfig: () => fromRight(),
});
package.json
...
"jest": {
"preset": "react-native",
"setupFiles": [
"<rootDir>/src/setupJest.js"
],
"transformIgnorePatterns": [
"node_modules/(?!(jest-)?react-native|react-navigation|react-navigation-redux-helpers|react-navigation-drawer)"
]
}
I think defaultNavigationOption is not a fat arrow function. From the docs of react-navigation:
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen
},
{
initialRouteName: 'Home',
/* The header config from HomeScreen is now here */
defaultNavigationOptions: {
headerStyle: {
backgroundColor: '#f4511e'
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold'
}
}
}
);