Been trying to migrate from react-portal from v2 to v4, due to recent upgrade of React to 16.8.6.
Stucked at Portal, whereby the dialog box doesn't show up even when isOpen=true. Found out that onOpen is not firing. Any suggestion on how should I change the codes?
import * as React from 'react';
import { Portal } from 'react-portal';
import 'dialog-polyfill/dialog-polyfill.css';
import 'dialog-polyfill/dialog-polyfill.js';
import { Dialog, DialogTitle, DialogContent, DialogActions, Button } from 'react-mdl';
class Confirm extends React.Component {
onOpen() {
if (!this.dialog.showModal) {
dialogPolyfill.registerDialog(this.dialog);
}
this.dialog.showModal();
}
closeDialog() {
this.dialog.close();
this.portal.closePortal();
}
render() {
const props = this.props;
return (
<Portal ref={c => this.portal = c} onOpen={this.onOpen.bind(this)} isOpen={Boolean(props.callback)} {...props}>
<dialog ref={c => this.dialog = c} className="mdl-dialog" style={props.style}>
<DialogTitle>{props.title}</DialogTitle>
<DialogContent>
{props.message}
</DialogContent>
<DialogActions>
<Button type='button' onClick={() => {this.closeDialog(); props.confirm();}}>Confirm</Button>
<Button type='button' onClick={() => {this.closeDialog(); props.dismissConfirmation();}}>Cancel</Button>
</DialogActions>
</dialog>
</Portal>
);
}
}
export default Confirm;
Expected Result: A confirmation dialog box to pop up.
From browser, already can see the dialog box is there by modifying the css.
Ended up realized it's due to openByClickOn no longer supported. As explained in:
openByClickOn Not Supported In React-Portal v4
Related
I want to shown an alert but my alert make to my app down scroll like this
alert image
i would like show that alert on the center and elevate it.
i tried with this css, but does not worked nothing
const styles = StyleSheet.create({
elevatedElement: {
zIndex: 3000000,
elevation: 3000000,
},
})
this is my code of the alert
import React, { useState } from 'react'
import { View } from 'react-native';
import { Button, Paragraph, Dialog, Portal, Provider } from 'react-native-paper';
const Alert = ({ show, setShow }) => {
return (
<Provider>
<View>
<Portal>
<Dialog visible={show} >
<Dialog.Title>Alert</Dialog.Title>
<Dialog.Content>
<Paragraph>This is simple dialog</Paragraph>
</Dialog.Content>
<Dialog.Actions>
<Button onPress={setShow}>Done</Button>
</Dialog.Actions>
</Dialog>
</Portal>
</View>
</Provider>
);
};
export default Alert;
and i am using that component like this
return (
<><Alert show={true} />
<Background>
<RightButton goRight={logout} />
<Logo />
</Background>
</>
)
According to the documentation for the Portal usage:
Portal allows rendering a component at a different place in the parent tree. You can use it to render content that should appear above other elements, similar to Modal. It requires a Portal. Host component to be rendered somewhere in the parent tree
So if you want to render the Portal on top of other elements like a modal you should use the Portal.Host:
**Note:**Try to implement thePortal component as the first element of Alert component without using the View element as below:
import { Portal } from 'react-native-paper';
// rest of the codes ...
return (
<Portal.Host>
<Dialog visible={show} >
<Dialog.Title>Alert</Dialog.Title>
<Dialog.Content>
<Paragraph>This is simple dialog</Paragraph>
</Dialog.Content>
<Dialog.Actions>
<Button onPress={setShow}>Done</Button>
</Dialog.Actions>
</Dialog>
</Portal.Host>
);
No need to set the zIndex or elevation style properties for this component.
Senario : I have a dialog, and i use a react-hook to make it disappear ,like const[show,setShow]= useState(false) , this dialog file is a seperate file with main screen file, which contain button to show this dialog
Problem : I don't know how to show this dialog in main screen, for example, my dialog file called Mydialog.js have componet Mydialog, so i tried to put that hook show in props , Mydialog(show), but look like it not work that way, i still can't show the dialog
Question. How can i use react-hook for multi file, like i have hook in dialog file, present the dialog status ( show or not) then i can use it in mainScreen file to set show to true, then i can use that show and set to false when click button in dialog
If I understood it right you're trying to bring up a dialog when you interact with something on the main page and then close it by clicking on the X within the dialog. Would something like this work?
Main.js:
import "./styles.css";
import { useState } from "react";
import MyDialog from "./MyDialog";
export default function App() {
const [showDialog, setShowDialog] = useState(false);
const handleDialog = () => {
setShowDialog(!showDialog);
};
return (
<>
<button onClick={handleDialog}>Show Dialog</button>
Show Dialog: {showDialog?.toString()}
{showDialog && <MyDialog handleDialog={handleDialog} />}
</>
);
}
MyDialog.js:
import "./styles.css";
export default function MyDialog({ handleDialog }) {
return (
<>
<div className="popup">
<div className="popup_open">
<h1>Dialog Content</h1>
<button onClick={handleDialog}>X</button>
</div>
</div>
</>
);
}
Sandbox link if you want to test: https://codesandbox.io/s/admiring-feather-sy1gf
You can use Context to maintain state between multiple components.
const DialogContext = createContext();
const DialogProvider = ({ children }) => {
const [isDialogVisible, setDialogVisible] = useState(false);
const value = {
isDialogVisible,
setDialogVisible,
}
return <DialogContext.Provider value={value}>{children}</DialogContext.Provider>
}
const useDialog = () => {
const context = useContext(DialogContext);
return context;
}
Render the DialogProvider in one of the top-level components, for example in App.js.
// App.js
return (
<DialogProvider>
// ...
</DialogProvider>
)
Then inside of your components you can use your hook and trigger the visibility of the dialog.
MyComponentA:
const { isDialogVisible, setDialogVisible } = useDialog();
const toggleDialogVisibility = () => {
setDialogVisible(!isDialogVisible);
}
return (
<Button title="Toggle" onPress={toggleDialogVisibility} />
)
MyComponentB:
const { isDialogVisible } = useDialog();
if(isDialogVisible) {
return <Text>My Dialog</Text>
}
return null;
A very simple example of usage, here's a Snack for the above.
Sorry for the dummy question, but I'm really stuck.
I created a very simple react-native app using these instructions.
Then I changed App.js to be
import React from 'react';
import {AppRegistry, Button, View } from 'react-native';
class RootView extends React.Component {
state = {
showFoo: false,
}
showFoo = () => {
this.setState({showFoo: true})
}
renderFoo = () => {
if (this.state.showFoo) {
console.log("at 4");
const item = <View />; /// BOOM!
console.log('at 5', item);
return item;
}
return null;
}
render = () => {
const renderFoo = this.renderFoo();
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
</View>
);
}
}
export default RootView;
Now, if I launch it using the Expo client on my Android 6.0.1. and I press "Press Me" button, it hangs and doesn't respond to back button.
In adb logcat, I can see "at 4", but never "at 5". It is like it stucks at "BOOM!" line for some reason (a dead lock?).
Wondering if I'm doing something wrong? My apologies again, but I have already spent a fair amount of time on this, would really appreciate any clue. Also, how could I debug things like that one?
Versions of react dependencies:
"dependencies": {
"expo": "^27.0.1",
"react": "16.3.1",
"react-native": "~0.55.2"
}
}
(Please let me know if you feel the question needs more details in the comments, I'm happy to update it.)
You should either use
<Button title="Press Me" onPress={this.showFoo.bind(this)}/>
or use
<Button title="Press Me" onPres{()=>this.showFoo()}/>
and also call this.renderFoo(); inside render method, with this syntax
{this.renderFoo()}
I've created a snack to show you the solution.
The problem is with your render method
render = () => {
const renderFoo = this.renderFoo();
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
</View>
);
}
Specifically const renderFoo = this.renderFoo();. For this line of code, you only execute the renderFoo method and store it into renderFoo variable, and it's not within the return portion. In other words the <View /> returned by renderFoo will not show on the screen.
The fix is by the below code
render() {
return (
<View>
<Button title="Press Me" onPress={this.showFoo} />
{this.renderFoo()}
</View>
);
}
Finally, after hours of investigation...
As it appears, the problem was this line:
console.log('at 5', item);
It hasn't actually stuck. If I waited for 5+ seconds, the app proceeded. Seems like logging a react component is a very expensive operation.
Same problem I had when I was trying to log some lambda function.
TLDR: don't log complex objects!!!!
React native for android run very slow when not enable "Debug JS"
https://facebook.github.io/react-native/docs/performance.html#using-consolelog-statements
I want to use external web page in my React Native App . I have button on my app and want to open external web page onPress button in my app not on browser.
I have tried WEBVIEW but not helped me.
now I have Tried this :
<HTMLView
value={this.props.html}
onLinkPress={(url) => alert('clicked link: ', url)}
/>
how can i do this ?
I have tried this and its working for me.
install react-native-custom-tabs using this command
npm install react-native-custom-tabs --save
and than link custom tabs package using
react-native link react-native-custom-tabs
and than call it
import {CustomTabs,ANIMATIONS_SLIDE,ANIMATIONS_FADE} from 'react-native-custom-tabs';
openCustomizedCustomTabs() {
this.openGoogle({
toolbarColor: '#607D8B',
enableUrlBarHiding: true,
showPageTitle: true,
enableDefaultShare: true,
animations: ANIMATIONS_SLIDE
});
}
errorOccur() {
this.openGoogle({
//toolbarColor: '607D8B', // <--- Invalid toolbar color.
enableUrlBarHiding: '#607D8B', // <-- Type Error.
})
}
openGoogle(option) {
CustomTabs.openURL('https://www.google.com', option).then((launched: boolean) => {
console.log(`Launched custom tabs: ${launched}`);
}).catch(err => {
console.error(err)
});
}
render(){
return <Button marginTop={10} onPress={() => this.openCustomizedCustomTabs()}>
Custom Tab
</Button>
}
and run app.
function renderNode(node, index, siblings, parent, defaultRenderer) {
if (node.name == 'iframe') {
const a = node.attribs;
const iframeHtml = `<iframe src="${a.src}"></iframe>`;
return (
<View key={index} style={{width: Number(a.width), height: Number(a.height)}}>
<WebView source={{html: iframeHtml}} />
</View>
);
}
}
class Page extends React.Component {
render() {
const htmlContent = `
<div>
<iframe src={this.props.utl} width="360" height="300" />
</div>
return (
<HTMLView value={htmlContent} renderNode={renderNode} />
);
}
}
then use it like:
<Page url="the url here..." />
React Native WebView Component has been Added in new Release to Documentation .
https://facebook.github.io/react-native/docs/webview.html
import React, { Component } from 'react';
import { WebView } from 'react-native';
class MyWeb extends Component {
render() {
return (
<WebView
source={{uri: 'https://github.com/facebook/react-native'}}
style={{marginTop: 20}}
/>
);
}
}
I'm trying to use shoutem/ui with exponent and I’m getting an error using the shoutem/ui textinput component, where I get the following error message fontFamily Rubik is not a system font and has not been loaded through Exponent.Font.loadAsync
However I loaded all the custom shoutem fonts that were listed in the blog post https://blog.getexponent.com/using-react-native-ui-toolkits-with-exponent-3993434caf66#.iyiwjpwgu
Using the Exponent.Font.loadAsync method.
fonts: [
FontAwesome.font,
{'space-mono': require('./assets/fonts/SpaceMono-Regular.ttf')},
{'Rubik-Black': require('./node_modules/#shoutem/ui/fonts/Rubik-Black.ttf')},
{'Rubik-BlackItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BlackItalic.ttf')},
{'Rubik-Bold': require('./node_modules/#shoutem/ui/fonts/Rubik-Bold.ttf')},
{'Rubik-BoldItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BoldItalic.ttf')},
{'Rubik-Italic': require('./node_modules/#shoutem/ui/fonts/Rubik-Italic.ttf')},
{'Rubik-Light': require('./node_modules/#shoutem/ui/fonts/Rubik-Light.ttf')},
{'Rubik-LightItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-LightItalic.ttf')},
{'Rubik-Medium': require('./node_modules/#shoutem/ui/fonts/Rubik-Medium.ttf')},
{'Rubik-MediumItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-MediumItalic.ttf')},
{'Rubik-Regular': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf')},
{'rubicon-icon-font': require('./node_modules/#shoutem/ui/fonts/rubicon-icon-font.ttf')},
],
});
Looking through the code I couldn't find the obvious fix - had trouble even finding where the style was set to throw the error.
The code above seem to be missing one line. Try adding this line to the array list:
{'Rubik': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf')}
Use this code from the link
import React, { Component } from 'react';
import { StatusBar } from 'react-native';
import { Font, AppLoading } from 'expo';
import { View, Examples } from '#shoutem/ui';
export default class App extends React.Component {
state = {
fontsAreLoaded: false,
};
async componentWillMount() {
await Font.loadAsync({
'Rubik': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf'),
'Rubik-Black': require('./node_modules/#shoutem/ui/fonts/Rubik-Black.ttf'),
'Rubik-BlackItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BlackItalic.ttf'),
'Rubik-Bold': require('./node_modules/#shoutem/ui/fonts/Rubik-Bold.ttf'),
'Rubik-BoldItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-BoldItalic.ttf'),
'Rubik-Italic': require('./node_modules/#shoutem/ui/fonts/Rubik-Italic.ttf'),
'Rubik-Light': require('./node_modules/#shoutem/ui/fonts/Rubik-Light.ttf'),
'Rubik-LightItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-LightItalic.ttf'),
'Rubik-Medium': require('./node_modules/#shoutem/ui/fonts/Rubik-Medium.ttf'),
'Rubik-MediumItalic': require('./node_modules/#shoutem/ui/fonts/Rubik-MediumItalic.ttf'),
'Rubik-Regular': require('./node_modules/#shoutem/ui/fonts/Rubik-Regular.ttf'),
'rubicon-icon-font': require('./node_modules/#shoutem/ui/fonts/rubicon-icon-font.ttf'),
});
this.setState({ fontsAreLoaded: true });
}
render() {
if (!this.state.fontsAreLoaded) {
return <AppLoading />;
}
return (
<View styleName="flexible">
<Examples />
<StatusBar barStyle="default" hidden={false} />
</View>
);
}
}