1import React, { Component } from 'react';
2import { StyleSheet, Button, View, TextInput } from 'react-native';
3import { Screen, ScreenStack } from 'react-native-screens';
4
5type StackProps = {
6  renderScreen: (key: string) => JSX.Element;
7};
8
9type StackState = {
10  stack: string[];
11  transitioning: number;
12};
13
14const COLORS = ['azure', 'pink', 'cyan'];
15
16export class Stack extends Component<StackProps, StackState> {
17  state = {
18    stack: ['azure'],
19    transitioning: 0,
20  };
21
22  push(key: string) {
23    const { stack } = this.state;
24    this.setState({ stack: [...stack, key], transitioning: 1 });
25  }
26
27  pop() {
28    const { stack } = this.state;
29    this.setState({ transitioning: 0, stack: stack.slice(0, -1) });
30  }
31
32  remove(index: number) {
33    const { stack } = this.state;
34    this.setState({ stack: stack.filter((v, idx) => idx !== index) });
35  }
36
37  removeByKey(key: string) {
38    const { stack } = this.state;
39    this.setState({ stack: stack.filter((v) => key !== v) });
40  }
41
42  renderScreen = (key: string) => {
43    return (
44      <Screen
45        style={StyleSheet.absoluteFill}
46        key={key}
47        stackAnimation="fade"
48        stackPresentation="push"
49        onDismissed={() => this.removeByKey(key)}>
50        {this.props.renderScreen(key)}
51      </Screen>
52    );
53  };
54
55  render() {
56    const screens = this.state.stack.map(this.renderScreen);
57    return <ScreenStack style={styles.container}>{screens}</ScreenStack>;
58  }
59}
60
61class App extends Component {
62  stackRef = React.createRef<Stack>();
63
64  renderScreen = (key: string) => {
65    const index = COLORS.indexOf(key);
66    const color = key;
67    const pop = index > 0 ? () => this.stackRef.current?.pop() : null;
68    const push = index < 2 ? () => this.stackRef.current?.push(COLORS[index + 1]) : null;
69    const remove = index > 1 ? () => this.stackRef.current?.remove(1) : null;
70
71    return (
72      <View
73        style={{
74          flex: 1,
75          backgroundColor: color,
76          alignItems: 'center',
77          justifyContent: 'center',
78          // margin: index * 40,
79        }}>
80        <View
81          style={{
82            position: 'absolute',
83            top: 110,
84            left: 0,
85            width: 80,
86            height: 80,
87            backgroundColor: 'black',
88          }}
89        />
90        {pop && <Button title="Pop" onPress={pop} />}
91        {push && <Button title="Push" onPress={push} />}
92        {remove && <Button title="Remove middle screen" onPress={remove} />}
93        <TextInput placeholder="Hello" style={styles.textInput} />
94        <View style={{ height: 100, backgroundColor: 'red', width: '70%' }} />
95      </View>
96    );
97  };
98
99  render() {
100    return <Stack ref={this.stackRef} renderScreen={this.renderScreen} />;
101  }
102}
103
104const styles = StyleSheet.create({
105  container: {
106    flex: 1,
107    justifyContent: 'center',
108    alignItems: 'center',
109    backgroundColor: '#F5FCFF',
110  },
111  textInput: {
112    backgroundColor: 'white',
113    borderWidth: 1,
114    padding: 10,
115    marginHorizontal: 20,
116    alignSelf: 'stretch',
117    borderColor: 'black',
118  },
119});
120
121export default App;
122