Skip to content

Instantly share code, notes, and snippets.

@Grohden
Last active May 22, 2019 13:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Grohden/7cf5b0d13824efe62b57f45b36ca1562 to your computer and use it in GitHub Desktop.
Save Grohden/7cf5b0d13824efe62b57f45b36ca1562 to your computer and use it in GitHub Desktop.
React navigation + react hooks problem with callback param
import React from 'react';
import {
createAppContainer,
createStackNavigator
} from 'react-navigation'
import TestScreen, {
testScreenOptions
} from './TestScreen'
const stack = createStackNavigator({
Test: {
screen: TestScreen,
navigationOptions: testScreenOptions
}
})
const Navigator = createAppContainer(stack)
export default () => <Navigator />
{
"dependencies": {
"react-native": "0.59.2",
"react": "16.8.3",
"react-navigation": "3.5.1"
}
}
import React, { useEffect, useState } from 'react';
import { Button, Text, View, StyleSheet, Image } from 'react-native';
let renderCount = 0
const TestScreen = (params) => {
const [fieldValue, setFieldValue] = useState('')
const handlePress = () => {
console.log(fieldValue)
// handlePress.value always 1 here
setFieldValue('' + handlePress.value)
}
handlePress.value = renderCount++
// Here we do a setParams to expose our callback
useEffect(() => {
params.navigation.setParams({ handlePress })
}, [fieldValue])
// if we add [fieldValue] as a dependency here,
// react will update the lambda and everything works.
// But this forces us to reference all
// used params in the handlePress.. which is
// EASY to miss and causes bugs that are HARD to find.
// Basically, every function used in the setParams
// should be pure to avoid reference/leak problems
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
value: {fieldValue}
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
padding: 24,
},
paragraph: {
margin: 24,
marginTop: 0,
fontSize: 14,
fontWeight: 'bold',
textAlign: 'center',
}
});
export const testScreenOptions = ({ navigation }) => ({
headerTitle: 'Test',
headerRight: (
<Button
mode='text'
onPress={ navigation.getParam('handlePress') }>
Press me
</Button>
)
})
export default TestScreen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment