After running test, the ad text display correctly, it displayed:
Your ad integration works. Whoohoo!
But no image displayed. I thought the <AdMediaView> show do the work, but it doesn't. What's wrong with my code?
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { FacebookAds } from 'expo';
FacebookAds.AdSettings.addTestDevice(FacebookAds.AdSettings.currentDeviceHash);
const adsManager = new FacebookAds.NativeAdsManager('my id', 1);
import AdComponent from './fbads.js';
export default class App extends React.Component {
render() {
return (
<View>
<Text>Hello!!</Text>
<View>
<AdComponent adsManager={adsManager} />
</View>
</View>
);
}
}
fbads.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { FacebookAds } from 'expo';
const { AdTriggerView, AdMediaView } = FacebookAds;
class AdComponent extends React.Component {
render() {
return (
<View>
<AdMediaView />
<AdTriggerView>
<Text>{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
</View>
);
}
}
export default FacebookAds.withNativeAd(AdComponent);
For anyone who still encounters this problem, try setting a fix width and height for the AdMediaView, and it should display after that. For example:
<AdMediaView style={{width: 400, height: 300}}/>
The same thing applies to AdIconView:
<AdIconView style={{width: 50, height: 50}}/>
OK, today I met this issue again. After a long time testing, I found that to show the image, I must place both AdIconView and AdMediaView.
This works:
<AdIconView style={{width: 50, height: 50}} />
<AdMediaView style={{width: 300, height: 200}} />
<AdTriggerView>
<Text>a{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
This doesn't work:
<AdMediaView style={{width: 300, height: 200}} />
<AdTriggerView>
<Text>a{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
Neither this:
<AdIconView style={{width: 50, height: 50}} />
<AdTriggerView>
<Text>a{this.props.nativeAd.bodyText}</Text>
</AdTriggerView>
Related
I want to use Expo Image Picker, but I'm getting the following error.
'Console Warning : possible unhandled promise rejection (id : 0)'.
I already installed 'expo-image-picker'.
Here's the promise code, I don't see what's wrong here, any ideas?
import { StatusBar } from 'expo-status-bar';
import React, { useState, useEffect } from 'react';
import { Platform, StyleSheet, Text, View, Button,Image } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import Constants from 'expo-constants';
export default function App() {
const [image,setImage] = useState(null);
useEffect(async () => {
if(Platform.OS !== 'web'){
const {status} = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted'){
alert('Permisson denied!')
}
}
}, []);
const PickImage = async() => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes : ImagePicker.mediaTypesOptions.All,
allowsEditing:true,
aspect:[4,3],
quality:1
})
console.log(result)
if(!result.cancelled ){
setImage(result.uri)
}
}
return (
<View style={styles.container}>
<Button title = "Choose Image" onPress = {PickImage}/>
{image && <Image source={{uri:image}} style = {{
width : 200,
height:200
}}/>}
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Assigning properties to mediatypes is incorrect.
Correction: mediaTypes:ImagePicker.MediaTypeOptions.All,
I'v try to make a SlectBox with react native.
To make that dropdown menu can be floated, I gava an absolute position to wrapper View, then make a clickable component with TouchableOpacity inside that View. It works well on Ios and Web, but not on android. There were many solutions on google like reordering component or give a zIndex to WrapperView or use Pressable etc.., but I could not find proper solution for my case.
Belows are my whole code. and You can test this code here.
Thank you in advance.
import {
Animated,
Easing,
Platform,
StyleProp,
TextStyle,
TouchableOpacity,
View,
ViewStyle,
} from 'react-native';
import {DoobooTheme, light, useTheme} from '../theme';
import React, {FC, ReactElement, useEffect, useRef, useState} from 'react';
import {Icon} from '../Icon';
import {Typography} from '../Typography';
import styled from '#emotion/native';
import {withTheme} from '#emotion/react';
const Title = styled.View`
width: 200px;
height: 30px;
border-width: 1px;
flex-direction: row;
justify-content: center;
align-items: center;
`;
const Item = styled.View`
height: 30px;
width: 200px;
border-bottom-width: 1px;
border-left-width: 1px;
border-right-width: 1px;
justify-content: center;
align-items: center;
`;
type Styles = {
titleContainer?: StyleProp<ViewStyle>;
titleText?: StyleProp<TextStyle>;
rightElementContainer?: StyleProp<ViewStyle>;
itemContainer?: StyleProp<ViewStyle>;
itemText?: StyleProp<TextStyle>;
};
interface ItemCompProps {
value: string;
order: number;
styles?: Styles;
setIsOpened: (value: boolean) => void;
itemActiveOpacity: number;
onPress?: (i: number) => void;
}
const ItemComp: FC<ItemCompProps> = ({
value,
order,
styles,
setIsOpened,
itemActiveOpacity,
onPress,
}) => {
const {theme} = useTheme();
const handlePress = (): void => {
onPress?.(order);
setIsOpened(false);
};
return (
<TouchableOpacity onPress={handlePress} activeOpacity={itemActiveOpacity}>
<Item
style={[
{
borderColor: theme.primary,
backgroundColor: theme.textContrast,
},
styles?.itemContainer,
]}>
<Typography.Body2 style={styles?.itemText}>{value}</Typography.Body2>
</Item>
</TouchableOpacity>
);
};
interface Props {
data: string[];
onPress?: (i: number) => void;
selectedIndex?: number;
theme?: DoobooTheme;
style?: StyleProp<ViewStyle>;
styles?: Styles;
rotateDuration?: number;
titleActiveOpacity?: number;
itemActiveOpacity?: number;
isRotate?: boolean;
rightElement?: ReactElement | null;
}
const Component: FC<Props> = ({
data,
onPress,
selectedIndex = 0,
style,
styles,
rotateDuration = 200,
titleActiveOpacity = 1,
itemActiveOpacity = 1,
isRotate: shouldRotate = true,
rightElement = <Icon name="chevron-down-light" />,
}) => {
const {theme} = useTheme();
const [isOpened, setIsOpened] = useState(false);
const rotateAnimValue = useRef(new Animated.Value(0)).current;
useEffect(() => {
const toValue = isOpened ? 1 : 0;
if (!shouldRotate) rotateAnimValue.setValue(toValue);
Animated.timing(rotateAnimValue, {
toValue,
duration: rotateDuration,
easing: Easing.linear,
useNativeDriver: Platform.OS !== 'web' ? true : false,
}).start();
}, [isOpened, rotateAnimValue, rotateDuration, shouldRotate]);
return (
<View style={[style]}>
<TouchableOpacity
onPress={() => setIsOpened((prev) => !prev)}
activeOpacity={titleActiveOpacity}>
<Title
style={[
{
borderColor: theme.primary,
backgroundColor: theme.textContrast,
},
styles?.titleContainer,
]}>
<Typography.Body2 style={styles?.titleText} testID="selected-value">
{data[selectedIndex]}
</Typography.Body2>
{rightElement ? (
<Animated.View
style={[
{
position: 'absolute',
right: 10,
transform: [
{
rotate: rotateAnimValue.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '180deg'],
}),
},
],
},
styles?.rightElementContainer,
]}>
{rightElement}
</Animated.View>
) : null}
</Title>
</TouchableOpacity>
<View>
<View style={{position: 'absolute'}}>
{isOpened &&
data.map((datum, key) => (
<ItemComp
key={key}
order={key}
value={datum}
styles={styles}
setIsOpened={setIsOpened}
onPress={onPress}
itemActiveOpacity={itemActiveOpacity}
/>
))}
</View>
</View>
</View>
);
};
Component.defaultProps = {theme: light};
export const SelectBox = withTheme(Component);
My solution
I resolved this problem with react-native-gesture-handler. :)
Install react-native-gesture-handler, then using TouchableOpacity from that.
Try to render out the component you want to be on top of stack below the component you want to bring below it
How I solve this issue:
I was implementing custom dynamic toaster using context to use it globally and wasn't able to access touchable opacity due to absolute positioning but i realized i was rendering my Toaster component before my main Stack Navigator which was bringing my toaster below navigation layer so i rendered it after stack navigator and it worked
BEFORE:
<ToasterContext.Provider value={{toasts:this.state.toastState, showToaster: this.showToaster,closeToaster: this.closeToaster }}>
<Provider store={store.store}>
<PersistGate loading={null} persistor={store.persistor}>
{toastState.length > 0
&& toastState.length <= 3
&& toastState.map((t, i) => {
return(
<DynamicToast i={i} key={i} t={t} position={"bottom"} duration={4000} closeToaster={this.closeToaster} />
)
}
)}
<NetworkConnectionModal/>
<AppContainer /> // I was rendering before my AppContainer
</PersistGate>
</Provider>
</ToasterContext.Provider>
AFTER: (Resolved my problem)
<ToasterContext.Provider value={{toasts:this.state.toastState, showToaster: this.showToaster,closeToaster: this.closeToaster }}>
<Provider store={store.store}>
<PersistGate loading={null} persistor={store.persistor}>
<NetworkConnectionModal/>
<AppContainer />
{toastState.length > 0
&& toastState.length <= 3
&& toastState.map((t, i) => {
return(
<DynamicToast i={i} key={i} t={t} position={"bottom"} duration={4000} closeToaster={this.closeToaster} />
)
}
)}
</PersistGate>
</Provider>
</ToasterContext.Provider>
Most of this is because the element is hidden behind other elements after absolute positioning.
Just like the picture in PPT is set to the bottom, but in some cases in HTML, you can still see your element. In this case, we need to set this element to the top.
Open the developer tool, select your element, add a Z-index to the element style of this element, and increase from 2 to see which value can just select your element. After confirmation, add a style to the project file.
z-index: 2,//add this to your component style
I am using expo ^40.0.0.
I am trying to get react-native-gesture-handler components to work in a <Modal> from react-native in Android. I followed docs here - https://docs.swmansion.com/react-native-gesture-handler/docs/#for-library-authors
It stays to wrap in <GestureHandlerRootView>, I did this but it doesn't fix the issue.
I created a snack demo of issue - https://snack.expo.io/#noitidart/frisky-carrot
Here you see a "Tapped here count: 0". Please try tapping it, you will see it doesn't increment the counter.
You will see a "RN BUTTON" this works but it is not from react-native-gesture-handler.
Here is my code from the snack:
import * as React from 'react';
import { Text, View, Modal, Button as RNButton } from 'react-native';
import {
BaseButton,
GestureHandlerRootView
} from 'react-native-gesture-handler';
export default function App() {
return (
<Modal animationType="slide" transparent={false}>
<Example />
</Modal>
);
}
const Example = function () {
const [cnt, setCnt] = React.useState(0);
return (
<View style={{ justifyContent: 'center', flex: 1 }}>
<RNButton title="rn button" onPress={() => alert('hi')} />
<GestureHandlerRootView>
<BaseButton
onPress={() => {
// alert('pressed');
setCnt(cnt + 1);
}}
>
<View style={{ backgroundColor: 'steelblue', height: 100 }}>
<Text>Tapped here count: {cnt}</Text>
</View>
</BaseButton>
</GestureHandlerRootView>
</View>
);
};
I am learning how to use React components on React Native and I am now starting the Handling Events. I created a handler that turns a text component to ON or OFF whenever the user presses the button. I managed to change the color of the button whenever the boolean value of the state changes but I haven't managed to do it with the backgroundColorof the screen. I tried to create a function {color} to render the color depending on the isToggleOn but my attempt was unsuccessful.
I think I have to pass a props to it but I don't know how to apply it in this case. Could you give me a hand?
import React from 'react';
import { View, Text, Button } from 'react-native';
import { render } from 'react-dom';
export default class HomeScreen extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((state) => ({
isToggleOn: !state.isToggleOn,
}));
}
render() {
//I tried to render the `color` by creating a function
const { color } = this.state.isToggleOn ? 'red' : 'blue';
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: color,
}}>
<Text>{this.state.isToggleOn ? 'ON' : 'OFF'}</Text>
<Button
color={this.state.isToggleOn ? 'red' : 'blue'}
title={this.state.isToggleOn ? 'TURN OFF' : 'TURN ON'}
onPress={this.handleClick}
/>
</View>
);
}
}
import React from 'react';
import {View, Text, Button} from 'react-native';
import { render } from 'react-dom';
export default class HomeScreen extends React.Component{
constructor(props) {
super(props);
this.state = {isToggleOn: true};
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(state => ({
// missing this here
isToggleOn: !this.state.isToggleOn
}));
}
render() {
// use variable
const color = this.state.isToggleOn ? 'red' : 'blue';
return(
<View
style={{
flex:1,
alignItems:'center',
justifyContent:'center',
backgroundColor:color}}>
<Text>
{this.state.isToggleOn ? 'ON' : 'OFF'}
</Text>
<Button color={this.state.isToggleOn ? 'red' : 'blue'} title={this.state.isToggleOn ? 'TURN OFF' : 'TURN ON'} onPress={this.handleClick}/>
</View>
)
}
}
Ciao, you could use a conditional style on View component like this:
<View style={this.state.isToggleOn ? styles.bg_red : styles.bg_blue}>
Then in your styles:
...
bg_blue: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "blue"
},
bg_red: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "red"
}
...
Here your code modified.
Having some trouble following the docs here federated with auth0 to add an extra login button that works to an existing project.
I have added the config object and created the app on the auth0 platform and configured cognito to use it as a federated login, but getting the button to work using the AWS Amplify withAuth0 HOC does not seem to work as expected. Either that or the docs are not clear.
I am getting the following error when clicking the button: the auth0 client is not configured
index.js
import "#babel/polyfill";
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import AppWithAuth from './appWithAuth';
import * as serviceWorker from './serviceWorker';
import { Provider } from 'react-redux';
import { createStore } from 'redux'
import rootReducer from './reducers'
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<AppWithAuth />
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
App.js
import React, { Component } from 'react';
import CssBaseline from '#material-ui/core/CssBaseline';
import { MuiThemeProvider, createMuiTheme, withStyles } from '#material-ui/core/styles';
import { BrowserRouter as Router } from "react-router-dom";
import { MuiPickersUtilsProvider } from '#material-ui/pickers';
import MomentUtils from '#date-io/moment';
import 'typeface-roboto';
import { connect } from 'react-redux';
import { setUserMetaLoaded, setPremiumUser, setAdminUser } from './actions';
import API from './api/appsync';
import Header from './components/header';
import MyRouter from './router';
import { library } from '#fortawesome/fontawesome-svg-core';
import { faLink } from '#fortawesome/free-solid-svg-icons';
import Amplify from 'aws-amplify';
library.add(faLink)
/*global AWS_CONFIG */
/*eslint no-undef: "error"*/
Amplify.configure(AWS_CONFIG);
const theme = createMuiTheme({
typography: { useNextVariants: true },
palette: {
primary: {
light: '#FDCF2A',
main: '#fe9e18',
dark: '#CC690B',
contrastText: '#ffffff',
}
},
});
const styles = theme => ({
root: {
display: 'flex',
flex: 1,
justifyContent: 'center',
padding: 20,
maxWidth: 1000,
margin: '0 auto',
flexDirection: 'column'
},
headerRoot: {
position: 'sticky',
top: 0,
paddingBottom: 3,
zIndex: theme.zIndex.appBar,
backgroundColor: theme.palette.background.default
}
})
class App extends Component {
async componentDidMount() {
const isAdmin = await API...
this.props.dispatch(setAdminUser(isAdmin));
const userMeta = await API...;
if(!userMeta) {
this.props.dispatch(setUserMetaLoaded(true));
this.props.dispatch(setPremiumUser(false));
return;
}
if(userMeta.hasOwnProperty('SubEnd')) {
const now = Math.floor(Date.now() / 1000);
if(userMeta['SubEnd'] > now) {
this.props.dispatch(setPremiumUser(true));
} else {
this.props.dispatch(setPremiumUser(false));
}
}
this.props.dispatch(setUserMetaLoaded(true));
}
render() {
const {classes} = this.props;
if (this.props.authState !== "signedIn") {
return null;
}
return (
<MuiThemeProvider theme={theme}>
<MuiPickersUtilsProvider utils={MomentUtils}>
<Router>
<CssBaseline />
<div className={classes.headerRoot}>
<Header />
</div>
<div className={classes.root}>
<MyRouter/>
</div>
</Router>
</MuiPickersUtilsProvider>
</MuiThemeProvider>
);
}
}
export default connect()(
withStyles(styles)(App)
);
appWithAuth.js
import React from "react";
import { SignIn, SignUp, forgotPassword, Greetings } from "aws-amplify-react";
import { default as CustomSignIn } from "./components/login";
import App from "./App";
import { Authenticator } from "aws-amplify-react/dist/Auth";
/*global AWS_CONFIG */
/*eslint no-undef: "error"*/
const config = AWS_CONFIG;
class AppWithAuth extends React.Component {
render() {
return (
<div>
<Authenticator hide={[SignIn, SignUp, forgotPassword, Greetings]} amplifyConfig={config}>
<CustomSignIn />
<App />
</Authenticator>
</div>
);
}
}
export default AppWithAuth;
The component to override the default login page from amplify
components/login/index.js
import React from "react";
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import TextField from '#material-ui/core/TextField';
import Link from '#material-ui/core/Link';
import Grid from '#material-ui/core/Grid';
import Typography from '#material-ui/core/Typography';
import { withStyles } from '#material-ui/core/styles';
import Container from '#material-ui/core/Container';
import { orange } from '#material-ui/core/colors';
import { SignIn } from "aws-amplify-react";
import ButtonAuth0 from "./../buttons/auth0"
const styles = theme => ({
'#global': {
body: {
backgroundColor: theme.palette.common.white,
},
},
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
form: {
width: '100%', // Fix IE 11 issue.
marginTop: theme.spacing(1)
},
cognito: {
margin: theme.spacing(3, 0, 2),
color: theme.palette.getContrastText(orange[600]),
backgroundColor: orange[600],
'&:hover': {
backgroundColor: orange[700]
}
}
});
class CustomSignIn extends SignIn {
constructor(props) {
super(props);
this._validAuthStates = ["signIn", "signedOut", "signedUp"];
}
showComponent(theme) {
const {classes} = this.props;
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<div className={classes.paper}>
<ButtonAuth0 />
<Typography component="h1" variant="h5">
Sign in
</Typography>
<form className={classes.form} noValidate>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
id="username"
label="Username"
name="username"
autoFocus
onChange={this.handleInputChange}
/>
<TextField
variant="outlined"
margin="normal"
required
fullWidth
name="password"
label="Password"
type="password"
id="password"
onChange={this.handleInputChange}
/>
<Button
type="submit"
fullWidth
variant="contained"
color="inherit"
className={classes.cognito}
onClick={(event) => super.signIn(event)}
>
Sign In With Cognito
</Button>
<Grid container>
<Grid item xs>
<Link href="#" variant="body2" onClick={() => super.changeState("forgotPassword")}>
Reset password?
</Link>
</Grid>
<Grid item>
<Link href="#" variant="body2" onClick={() => super.changeState("signUp")}>
{"Don't have an account? Sign Up"}
</Link>
</Grid>
</Grid>
</form>
</div>
</Container>
);
}
}
export default (withStyles(styles)(CustomSignIn));
The button component:
components/buttons/auht0.js
import React from 'react';
import { withAuth0 } from 'aws-amplify-react';
import Button from '#material-ui/core/Button';
import { red } from '#material-ui/core/colors';
import { withStyles } from '#material-ui/core';
import { Auth } from 'aws-amplify';
const auth0 = {
"domain": "<...>",
"clientID": "<...>",
"redirectUri": "http://localhost:3000",
"audience": "",
"responseType": "token id_token", // for now we only support implicit grant flow
"scope": "openid profile email", // the scope used by your app
"returnTo": "http://localhost:3000"
};
Auth.configure({
auth0
});
const styles = theme => ({
auth0: {
margin: theme.spacing(3, 0, 2),
color: theme.palette.getContrastText(red[700]),
backgroundColor: red[700],
'&:hover': {
backgroundColor: red[800]
}
}
});
const Auth0Button = (props) => (
<div>
<Button
fullWidth
variant="contained"
color="inherit"
className={props.classes.auth0}
onClick={props.auth0SignIn}
>
Sign In With auth0
</Button>
</div>
)
export default withAuth0(withStyles(styles)(Auth0Button));
Is this supposed to work on its own or do steps 1 to 4 of the docs in the link above still need to be followed?
Answering my own question here. Strangely I had somehow not tried this.
Looking at the source code, I tried passing the auth0 configuration object to the withAuth0 initialisation and got rid of that error message.
export default withAuth0(withStyles(styles)(Auth0Button), auth0);