magicismight/react-native-root-siblings(新しいタブで開きます)
主要言語: TypeScript
A sibling elements manager.
- star 数
- 734
- watcher 数
- 6
- fork 数
- 133
- issue 数
- 17
- 最終更新
- 2024/05/16
主要言語: TypeScript
A sibling elements manager.
The easiest way to create overlays(Modal, Popover, Dialog etc) for both react and react-native.
Make your own showModal and use it in any component without any isShow state or even in a pure function call.
import RootSiblingsManager from 'react-native-root-siblings'; export const showModal = (renderModal) => { let rootNode; const onClose = () => { rootNode?.destroy(); rootNode = null; }; rootNode = new RootSiblingsManager(renderModal(onClose)); return onClose; }; import WelcomeModal from './WelcomeModal'; export function showWelcomeModal() { showModal((onClose) => <WelcomeModal onClose={onClose} />); } // ... function HomeScreen() { return <Button onClick={showWelcomeModal}>Welcome!</Button> } setTimeout(showWelcomeModal, 3000);
npm i react-native-root-siblings
Insert RootSiblingParent between your providers and root app in your root render function.
import { RootSiblingParent } from 'react-native-root-siblings'; return ( <SomeProviders> <RootSiblingParent> // <- use RootSiblingParent to wrap your root component <App /> </RootSiblingParent> </SomeProviders> );
RootSiblingParent works as a mounting base and can be mounted multiple times. Only the last mounted one would be active.
In react native, a view has a higher hierarchy if it's more close to the root level.
<RootSiblingParent> <RootView> // <- the highest view <NavigationView> <ScreenView> // <- the lowest view { /* what if you want to show a fullscreen modal here? * usually you have to use a Native Modal which is even higher than RootView * but it's buggy and has a lot of limitations */} <RootSiblingPortal> { /* View put in here would be transported to RootSiblingParent * So it can have a same hierarchy as the RootView to cover any other views */} <View> </View> </RootSiblingPortal> </ScreenView> </NavigationView> </View> </RootSiblingParent>
In react we have createPortal but still it's not so convenient as it can not be used outside of a component.
react-native-root-siblings provides the most possible flexibility:
let sibling = new RootSiblings(<View style={{top: 0,right: 0,bottom: 0,left: 0,backgroundColor: 'red'}} />);
This will create a View element cover all of your app elements, and returns a sibling instance. You can create a sibling anywhere, no matter in a component, hook or even a pure function.
sibling.update(<View style={{top: 10,right: 10,bottom: 10,left: 10,backgroundColor: 'blue'}} />);
This will update the sibling instance to a View with blue backgroundColor and cover the screen by 10 offset distance.
sibling.destroy();
This will remove the sibling element.
import { RootSiblingPortal } from 'react-native-root-siblings'; class extends Component { render() { return ( <RootSiblingPortal> <View style={[StyleSheet.absoluteFill, { backgroundColor: 'rgba(0, 0, 0, 0.25)' }]} /> </RootSiblingPortal> ) } }
import React, { AppRegistry, View, Component, TouchableHighlight, StyleSheet, Text } from 'react-native'; import Dimensions from 'Dimensions'; // Import library there,it will wrap everything registered by AppRegistry.registerComponent // And add or remove other elements after the root component import RootSiblings from 'react-native-root-siblings'; var id = 0; var elements = []; class SiblingsExample extends Component{ addSibling = () => { let sibling = new RootSiblings(<View style={[styles.sibling, {top: id * 20}]} > <Text>I`m No.{id}</Text> </View>); id++; elements.push(sibling); }; destroySibling = () => { let lastSibling = elements.pop(); lastSibling && lastSibling.destroy(); }; updateSibling = () => { let lastId = elements.length - 1; lastId >= 0 && elements[lastId].update(<View style={[styles.sibling, {top: lastId * 20}]} > <Text>I`m No.{lastId} : {Math.random()}</Text> </View>); }; render() { return <View style={styles.container}> <TouchableHighlight style={styles.button} onPress={this.addSibling} > <Text style={styles.buttonText}>Add element</Text> </TouchableHighlight> <TouchableHighlight style={styles.button} onPress={this.destroySibling} > <Text style={styles.buttonText}>Destroy element</Text> </TouchableHighlight> <TouchableHighlight style={styles.button} onPress={this.updateSibling} > <Text style={styles.buttonText}>Update element</Text> </TouchableHighlight> </View>; } } AppRegistry.registerComponent('SiblingsExample', () => SiblingsExample); var styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'green', }, button: { borderRadius: 4, padding: 10, marginLeft: 10, marginRight: 10, backgroundColor: '#ccc', borderColor: '#333', borderWidth: 1, }, buttonText: { color: '#000' }, sibling: { left: 0, height: 20, width: Dimensions.get('window').width / 2, backgroundColor: 'blue', opacity: 0.5 } });