Skip to content

Commit f40715c

Browse files
authored
Fix: Possible fix for #13 - Node re-creation on the native side (#14)
* hack: add a recreate method on each child node tree there's a new recreate method which get's fired everytime something is removed, since react native also removes it's existence from the native side causing re- mounting errors * simplify examples * add rebuildTree on append instead of remove * add a multipage example component * simplify nested condition for removal * change the increment count for allocation of tags hack to avoid colliding tags with react native * ci: disable build * chore: proper demo
1 parent d884984 commit f40715c

File tree

13 files changed

+468
-204
lines changed

13 files changed

+468
-204
lines changed

.codesandbox/ci.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"sandboxes": ["vanilla"],
3-
"node": "14"
3+
"node": "14",
4+
"buildCommand": false
45
}

example/App.js

+9-172
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,12 @@
11
/** @jsxImportSource preact */
2+
import DomApp from './components/DomCounter'
3+
import MultiPage from './components/MultiPage'
4+
import PreactCounter from './components/PreactCounter'
5+
import { Demo } from './components/Demo'
26

3-
import { TextInput, Text, View, SafeAreaView } from '@barelyhuman/preact-native'
4-
import { Component } from 'preact'
5-
import { signal } from '@preact/signals'
6-
import { Alert } from 'react-native'
7-
import { createApp, h as vueJSX } from 'vue'
8-
9-
function App() {
10-
// VueCounter()
11-
return <Counter />
12-
}
13-
14-
// FIXME: event handlers compat for vue
15-
function VueCounter() {
16-
const saView = document.createElement('SafeAreaView')
17-
document.appendChild(saView)
18-
19-
const app = createApp({
20-
data() {
21-
return {
22-
count: 0,
23-
}
24-
},
25-
render() {
26-
return vueJSX(
27-
'View',
28-
{
29-
style: {
30-
backgroundColor: '#333',
31-
height: 52,
32-
justifyContent: 'center',
33-
alignItems: 'center',
34-
borderRadius: 6,
35-
},
36-
},
37-
vueJSX('Text', { style: { color: 'white' } }, this.count)
38-
)
39-
},
40-
})
41-
app.mount(saView)
42-
}
43-
44-
const count = signal(0)
45-
46-
function Counter() {
47-
const handleInc = e => {
48-
e.stopPropagation()
49-
count.value++
50-
}
51-
52-
const handleDec = e => {
53-
e.stopPropagation()
54-
count.value--
55-
}
56-
57-
return (
58-
<>
59-
<SafeAreaView>
60-
<View alignItems="center" justifyContent="center">
61-
<Text fontSize={30} margin={10} color="white">
62-
{count.value}
63-
</Text>
64-
<View>
65-
<View
66-
onClick={handleInc}
67-
borderRadius={6}
68-
width={250}
69-
margin={10}
70-
backgroundColor={'#333'}
71-
alignItems="center"
72-
justifyContent="center"
73-
>
74-
<Text fontSize={30} margin={10} color="white">
75-
+
76-
</Text>
77-
</View>
78-
79-
<View
80-
onClick={handleDec}
81-
borderRadius={6}
82-
width={250}
83-
margin={10}
84-
backgroundColor={'#333'}
85-
alignItems="center"
86-
justifyContent="center"
87-
>
88-
<Text fontSize={30} margin={10} color="white">
89-
-
90-
</Text>
91-
</View>
92-
</View>
93-
</View>
94-
</SafeAreaView>
95-
</>
96-
)
7+
export default function App() {
8+
// DomApp()
9+
// return <MultiPage />
10+
// return <PreactCounter />
11+
return <Demo />
9712
}
98-
99-
class TestRenderable extends Component {
100-
state = { email: '' }
101-
constructor(props) {
102-
super(props)
103-
}
104-
105-
render() {
106-
return (
107-
<>
108-
<SafeAreaView backgroundColor="#181819">
109-
<View
110-
height="100%"
111-
width="100%"
112-
padding={10}
113-
alignItems="center"
114-
justifyContent="center"
115-
>
116-
<TextInput
117-
width={'100%'}
118-
height={52}
119-
marginBottom={8}
120-
padding={10}
121-
placeholder="email"
122-
borderRadius={10}
123-
borderWidth={1}
124-
borderColor="slategray"
125-
color="white"
126-
value={this.state.email}
127-
backgroundColor="transparent"
128-
onFocus={e => {
129-
console.log('focus')
130-
}}
131-
onBlur={e => {
132-
console.log('blur')
133-
}}
134-
onChange={e => {
135-
this.setState({ email: e.data })
136-
}}
137-
/>
138-
<TextInput
139-
width={'100%'}
140-
height={52}
141-
marginBottom={8}
142-
padding={10}
143-
placeholder="password"
144-
secureTextEntry={true}
145-
borderRadius={10}
146-
borderWidth={1}
147-
borderColor="slategray"
148-
color="white"
149-
backgroundColor="transparent"
150-
/>
151-
<View
152-
height={52}
153-
padding={15}
154-
width={'100%'}
155-
borderRadius={6}
156-
justifyContent="center"
157-
alignItems="center"
158-
backgroundColor="white"
159-
onClick={e => {
160-
e.stopPropagation()
161-
Alert.alert(`Oh hey, ${this.state.email}`)
162-
}}
163-
>
164-
<Text fontSize={16} fontWeight="bold">
165-
Login
166-
</Text>
167-
</View>
168-
</View>
169-
</SafeAreaView>
170-
</>
171-
)
172-
}
173-
}
174-
175-
export default App

example/components/Demo.js

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/**@jsxImportSource preact*/
2+
import { Component } from 'preact'
3+
import { SafeAreaView, Text, View } from '@barelyhuman/preact-native'
4+
import { StyleSheet } from 'react-native'
5+
6+
export class Demo extends Component {
7+
state = {
8+
activeTab: 0,
9+
}
10+
render() {
11+
return (
12+
<>
13+
<SafeAreaView height={'100%'} backgroundColor={'#673ab8'}>
14+
<View
15+
padding={12}
16+
flexDirection={'row'}
17+
backgroundColor={'#673ab8'}
18+
alignItems={'baseline'}
19+
justifyContent={'space-between'}
20+
>
21+
<View>
22+
<Text fontSize={24} style={styles.primaryText}>
23+
Preact Native
24+
</Text>
25+
</View>
26+
<View flexDirection={'row'} alignItems={'baseline'}>
27+
<View
28+
style={styles.tabView}
29+
borderColor={
30+
this.state.activeTab === 0 ? '#ad80ff' : 'transparent'
31+
}
32+
onClick={() => {
33+
this.setState({
34+
activeTab: 0,
35+
})
36+
}}
37+
>
38+
<Text style={styles.primaryText}>About</Text>
39+
</View>
40+
<View
41+
style={styles.tabView}
42+
borderColor={
43+
this.state.activeTab === 1 ? '#ad80ff' : 'transparent'
44+
}
45+
onClick={() => {
46+
this.setState({
47+
activeTab: 1,
48+
})
49+
}}
50+
>
51+
<Text style={styles.primaryText}>Counter</Text>
52+
</View>
53+
</View>
54+
</View>
55+
<View style={styles.tabPageContainer}>
56+
<About show={this.state.activeTab === 0} />
57+
<Counter show={this.state.activeTab === 1} />
58+
</View>
59+
</SafeAreaView>
60+
</>
61+
)
62+
}
63+
}
64+
65+
function About({ show }) {
66+
if (!show) {
67+
return null
68+
}
69+
return (
70+
<>
71+
<Text color={'#ccc'}>
72+
Preact Native, as of now is an experimental approach at connecting the
73+
react-native SDK to the preact web UI library
74+
</Text>
75+
</>
76+
)
77+
}
78+
79+
class Counter extends Component {
80+
state = {
81+
count: 0,
82+
focused: false,
83+
}
84+
85+
render({ show }) {
86+
if (!show) {
87+
return null
88+
}
89+
return (
90+
<View justifyContent="center" alignItems="center">
91+
<Text style={styles.primaryText} fontSize={24}>
92+
{this.state.count}
93+
</Text>
94+
<View
95+
style={styles.button}
96+
backgroundColor={this.state.focused ? 'white' : 'transparent'}
97+
marginTop={20}
98+
onClick={() => {
99+
this.setState(() => ({
100+
focused: true,
101+
count: this.state.count + 1,
102+
}))
103+
setTimeout(() => {
104+
this.setState(() => ({
105+
focused: false,
106+
}))
107+
}, 250)
108+
}}
109+
>
110+
<Text
111+
style={styles.buttonText}
112+
color={this.state.focused ? 'black' : 'white'}
113+
>
114+
Inc
115+
</Text>
116+
</View>
117+
</View>
118+
)
119+
}
120+
}
121+
122+
const styles = StyleSheet.create({
123+
tabView: {
124+
marginHorizontal: 2,
125+
padding: 4,
126+
borderTopWidth: 4,
127+
},
128+
primaryText: {
129+
color: '#fff',
130+
},
131+
secondaryText: {
132+
color: '#ccc',
133+
},
134+
tabPageContainer: {
135+
marginTop: 12,
136+
padding: 12,
137+
height: '100%',
138+
backgroundColor: '#1c2027',
139+
},
140+
button: {
141+
borderRadius: 6,
142+
borderWidth: 3,
143+
justifyContent: 'center',
144+
alignItems: 'center',
145+
borderColor: '#fff',
146+
marginHorizontal: 16,
147+
minWidth: 200,
148+
paddingHorizontal: 32,
149+
paddingVertical: 12,
150+
},
151+
buttonText: {
152+
fontSize: 18,
153+
},
154+
})

example/components/DomCounter.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
export default function DomApp() {
2+
let count = 0
3+
4+
const saView = document.createElement('SafeAreaView')
5+
const view = document.createElement('View')
6+
const text = document.createElement('Text')
7+
text.textContent = count
8+
9+
Object.assign(text.style, {
10+
color: 'white',
11+
fontSize: 24,
12+
})
13+
14+
Object.assign(view.style, {
15+
backgroundColor: 'dodgerblue',
16+
padding: 16,
17+
borderRadius: 6,
18+
margin: 10,
19+
justifyContent: 'center',
20+
alignItems: 'center',
21+
})
22+
23+
view.addEventListener('click', e => {
24+
e.stopPropagation()
25+
text.textContent = ++count
26+
})
27+
28+
view.appendChild(text)
29+
saView.appendChild(view)
30+
document.appendChild(saView)
31+
32+
return null
33+
}

0 commit comments

Comments
 (0)