React native use a local font on snack.expo.io - javascript

How can I use a local font on snack.expo.io?
I have a ttf font, which I would like to use as evidence on snack.expo.io, but I do not quite understand how I could do it.
Some advice?

When you are creating your snack you can import files. You can see beside Project there are three vertical dots, click that takes you to the import menu.
Selecting Import files will take you to this screen where you can either browse or drag and drop your files. I prefer to drag and drop.
You can then drag the files to the folder that you wish them to be located in.
Then to use your custom font you can follow the guide in the documentation.
https://docs.expo.io/versions/latest/guides/using-custom-fonts/
Here is a quick code example.
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants, Font } from 'expo';
// You can import from local files
export default class App extends React.Component {
// <- use the button on the left, three vertical dots to import files
// set the initial state
state = {
fontLoaded: false
}
async componentDidMount() {
// load fonts
await this.loadFonts();
}
loadFonts = async () => {
// load the font
await Font.loadAsync({
'open-sans-bold': require('./assets/fonts/OpenSans-Bold.ttf'),
});
this.setState({fontLoaded: true})
}
render() {
// use the font in your text components
// only render the Text component when the font has been loaded.
return (
<View style={styles.container}>
{this.state.fontLoaded ? (<Text style={{ fontFamily: 'open-sans-bold', fontSize: 56 }}>
Hello, world!
</Text>) : null}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
}
});
And an accompanying snack to show it working, notice I have stored my fonts in the folder ./assets/fonts/ https://snack.expo.io/#andypandy/custom-font

Related

Mass import and loading of images in React with react-three-fiber

I am currently trying to import and use ~300 images (.png files) in my react project. They should be displayed inside a 3D view and loaded using the loader of react-three-fiber.
I have therefore copied the files to a folder named images and created a file index.js which exports the images as follows:
export { default as image_0 } from './0.png';
export { default as image_1 } from './1.png';
[...]
I previously also tried to export the images like this:
import image_0 from './0.png';
import image_1 from './1.png'
[...]
export {
image_0,
image_1,
[...]
}
The images are then loaded in another file:
import * as imageArray from "../../../assets/textures/images"
try {
texture = useLoader(THREE.TextureLoader, imageArray['sign_' + imageNumber]);
} catch (e) {
console.log("Image for number " + imageNumber + " not found.");
}
When testing this workflow without the try/catch I always get the following error inside the developer tools console:
Uncaught Could not load undefined: undefined
I have double checked that the corresponding images are present in images and that there is no naming error. After that I also tried to set all textures to one file which has been declared missing but was definitely inside the folder and therefore loadable:
texture = useLoader(THREE.TextureLoader, imageArray['sign_x']);
I again got the same error and the image could not be loaded.
My guess is that this is a problem caused by too many imported images but I could not find any other solution to import such a high number of files in a project. I would really appreciate any help. Thank you very much in advance!
I dont think the issue is the large imports. I think (Im not certain) that its an import vs require thing. In the docs for expo-three they are using require. I also notice that for images require return an id rather than the files themselves, which may be key to solving your issue.
Here's a demo where I use require to get 130 images, load them with ExpoTHREE.TextureLoader, and then provide them as optional textures for a threejs cube:
import React, { useEffect, useState } from 'react';
import {
Text,
useWindowDimensions,
StyleSheet,
Platform,
Image,
} from 'react-native';
import * as Progress from 'react-native-progress';
import { Asset } from 'expo-asset';
import { TextureLoader, loadAsync, THREE } from 'expo-three';
import Constants from 'expo-constants';
import ThreeWrapper from './components/ThreeWrapper';
import SafeAreaView from './components/SafeAreaView'
import imageArray from './assets/images/index';
global.THREE = global.THREE || THREE;
export default function App({ onComplete, ...props }) {
const [progress, setProgress] = useState(0.0);
const [textures, setTextures] = useState([]);
const { width, height } = useWindowDimensions();
const loadTextures = async () => {
const values = Object.entries(imageArray);
const total = values.length;
const imgs = await Promise.all(
values.map(async ([currentKey, requiredId]) => {
try {
let [{ uri, localUri }] = await Asset.loadAsync(requiredId);
const url = Platform.OS == 'android'
// android needs this?
? uri
:localUri
const texture = new TextureLoader().load(url);
setProgress((prev) => prev + 1 / total);
return texture;
} catch (err) {
console.log(err);
}
})
);
setTextures(imgs);
};
useEffect(() => {
loadTextures();
}, []);
if (Math.round(progress * 1000) / 1000 < 1)
return (
<SafeAreaView style={styles.container}>
<Text style={{ fontSize: 38, fontWeight: 'bold' }}>Loading...</Text>
<Progress.Bar
progress={progress}
width={width * 0.8}
height={36}
borderRadius={50}
/>
<Text
style={{
fontSize: 24,
fontWeight: '300',
textAlign: 'center',
width: '100%',
}}>
{(progress * 100).toFixed(2) + '%'}
</Text>
</SafeAreaView>
);
return (
<SafeAreaView style={styles.container}>
<ThreeWrapper textures={textures} />
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});

Why when I try to use react native hooks it does not work properly as intended to be?

I am developing an app using react native, when I try to console.log(useDeviceOrientation());. The output (true/false) during the portrait and landscape did not change. Could someone help?
The library that is used is: #react-native-community/hooks
API that I used: useDeviceOrientation
What I try to do:
uninstall the library
reinstall the same library
add dependencies of the library to package.json
same problem occurred. no changes when changing orientation
Code:
// import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { Dimensions, StyleSheet, SafeAreaView, Alert, Button, Platform, StatusBar, View } from 'react-native';
import { useDimensions, useDeviceOrientation } from '#react-native-community/hooks'
export default function App() {
console.log(useDeviceOrientation());
const { landscape } = useDeviceOrientation();
return (
<SafeAreaView style={styles.container}>
<View style={{
backgroundColor: "dodgerblue",
width: "100%",
height: landscape ? "100%" : "30%",
}}
></View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
// justifyContent: "center",
// alignItems: "center",
},
});
There is no need for 3rd party library for this. You can use this approach.
First, create a functional component named useOrientarion,
import { useWindowDimensions } from 'react-native';
const useOrientation = () => {
const { width, height } = useWindowDimensions();
return { isPortrait: height > width };
};
export default useOrientation;
and then in your component,
// import useOrientation
import useOrientation from './useOrientation';
function App() {
const orientation = useOrientation();
console.log(orientation);
// use orientation wherever you want
// OUTPUT: {"isPortrait": true} or {"isPortrait": false}
}
it works for me.
const { height, width } = useDimensions().window;
const landscape = width > height;
react-native-community
I believe it is a known issue that they are working on: https://github.com/react-native-community/hooks/issues/210. #ReadRise answer works great as a workaround it though!
I had the same issue; stopping the app and re-building was sufficient to have it fixed.

Fonts not applied on style unless hot-reloaded in React-Native

I am using global object to store font names (so later I can change all the fonts), but some how they not applied unless I save the component (and trigger hot-reload).
After experiments I found that global do not store values in the beginning, so the hot reload have to re-assign values to global variables that closured.
Code:
App.jsx
...
global.fontRegular = 'Montserrat-Regular';
global.fontSemiBold = 'Montserrat-SemiBold';
global.fontExtraBold = 'Montserrat-ExtraBold';
...
HeaderTitle.jsx
import React from 'react';
import {Text, TouchableOpacity, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
text: {
fontSize: 24,
color: '#f1f1f1',
textAlign: 'center',
fontFamily: global.fontExtraBold,
margin: 10,
},
});
export default function () {
return (
<TouchableOpacity>
<Text style={styles.text}>SUPPORT.UA</Text>
</TouchableOpacity>
);
}
Screen before hot-reload
Screen after hot-reload
What I found out, is that using global object do not work for enclosured object if not in export body, so original code WILL NOT WORK,
but the following one WILL (now I wonder how this works):
import React from 'react';
import {Text, TouchableOpacity, StyleSheet} from 'react-native';
export default React.memo(function ({navigation, ...props}) {
const styles = StyleSheet.create({
text: {
fontSize: 24,
color: '#f1f1f1',
textAlign: 'center',
fontFamily: global.fontExtraBold,
margin: 10,
},
});
return (
<TouchableOpacity onPress={() => navigation.navigate('MainScreen')}>
<Text style={styles.text}>SUPPORT.UA</Text>
</TouchableOpacity>
);
});
Your const styles object is declared outside a function block, therefore it is evaluated immediately on app launch (with global.yourFont being unassigned yet). However, assignments to global are operations, that are done after the entire code has been crawled and unscoped const's have been evaluated. Therefore, moving it inside a component fixes the problem, because the component function will be called way after the initial crawl.

How to override styles in a react-chartist component?

I have a simple React JS component that wraps around the really cool react ChartistGraph component. The only issue is that the styling is seemingly overridden by the ChartistGraph default CSS. There is a lot of info on the regular Chartist js package but not much on the React JS package.
As you can see, I'm trying to change the fill color two ways: through style classes and through a prop that supported on the component.
import React from 'react';
import { Paper, withStyles } from 'material-ui';
import ChartistGraph from 'react-chartist';
const styles = theme => ({
graphStyle: {
fill: 'red',
},
});
const CustomChart = ({ classes, graph }) => {
return (
<Paper>
<ChartistGraph
className={classes.graphStyle}
data={graph.data}
options={graph.options}
type={graph.type}
style={{ fill: 'red' }}
/>
</Paper>
);
};
export default withStyles(styles)(CustomChart);
A picture of the styles of the chart
You can use jss's nested rules (included by default in material-ui):
const styles = theme => ({
graphStyle: {
'& .ct-label': { fill: 'red' },
},
});
Full code:
import React from 'react';
import { Paper, withStyles } from 'material-ui';
import ChartistGraph from 'react-chartist';
const styles = theme => ({
graphStyle: {
'& .ct-label': { fill: 'red' },
},
});
const CustomChart = ({ classes, graph }) => {
return (
<Paper>
<ChartistGraph
className={classes.graphStyle}
data={graph.data}
options={graph.options}
type={graph.type}
// style={{ fill: 'red' }} // omitted
/>
</Paper>
);
};
export default withStyles(styles)(CustomChart);
I got into similar issue recently.React-Chartist is built on top of react not material-ui.When you inspect,you found regular css class names,not "material ui-ish" class-names(like MuiTable-root,MuiTable-selectedRow,etc).So ,imho,it won't support material-ui methods (withStyle/makeStyle) and rules.
But what you can do is:-
create a css file and put your styles there
And import it where you want
.You can import it on the main file of your app(index.js or whatever it is) since every css in your app will bundle in one file.

React native drawer menu: can`t find variable styles

I am trying to create a slider menu with the react-native-drawer-menu module. After installing the module . get an error can`t find variable styles. This is the code copied from the example:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux'
import'../I18n/I18n.js';
import RootContainer from './RootContainer'
import createStore from '../Redux'
import Drawer from 'react-native-drawer-menu';
import {Easing} from 'react-native'; // Customize easing function (Optional)
// create store
const store = createStore()
export default class App extends React.Component {
render() {
// prepare your drawer content
var drawerContent = (<View style={styles.drawerContent}>
<View style={styles.leftTop}/>
<View style={styles.leftBottom}>
<View><Text>Drawer Content</Text></View>
</View>
</View>);
var customStyles = {
drawer: {
shadowColor: '#000',
shadowOpacity: 0.4,
shadowRadius: 10
},
mask: {}, // style of mask if it is enabled
main: {} // style of main board
};
return (
<Drawer
style={styles.container}
drawerWidth={300}
drawerContent={drawerContent}
type={Drawer.types.Overlay}
customStyles={{drawer: styles.drawer}}
drawerPosition={Drawer.positions.Right}
onDrawerOpen={() => {console.log('Drawer is opened');}}
onDrawerClose={() => {console.log('Drawer is closed')}}
easingFunc={Easing.ease}
>
<View style={styles.content}>
<Text>{Object.values(Drawer.positions).join(' ')}</Text>
<Text>{Object.values(Drawer.types).join(' ')}</Text>
</View>
</Drawer>
);
}
}
If I delete the variable from the code then the slide menu works but looks extremely bad.
Do you think that I am supposed to create the style of the menu on my own or shall I imported from somewhere? If I have to create it, how can I know which parameters did it take? Or is it a normal view?
Looks like you have to add styles by yourself to make look Drawer content exactly as you want to. To achieve it you have to create Stylesheet
You can use this answer to get more info about React Native Stylesheet properties (it's pretty much similar to css)
Also maybe this example from drawer repo would be helpful
Cheers.

Categories