Search code examples
reactjsreact-nativereact-props

How can I implement D.R.Y. in my FlatList when re-using the same props passed to an OnPress?


Learning React Native I set out to use FlatList and React Navigation and while everything works I've been searching for a way to prevent calling the same props. In my Parent component:

const Parent = ({ navigation }) => {
  return (
    <>
      <StatusBar hidden />
      <FlatList
        data={data}
        renderItem={({ item }) => (
          <Child
            title={item.name}
            color={item.color}
            onPress={() =>
              navigation.navigate(routes.PATH, {
                title: item.name,
                foo: item.foo,
                color: item.color,
              })
            }
          />
        )}
        keyExtractor={item => item.id.toString()}
      />
    </>
  )
}

Parent.propTypes = {
  navigation: PropTypes.object.isRequired,
}

I pass down everything to my Child component:

const Child = ({ onPress = () => {}, title, color }) => {
  return (
    <TouchableOpacity onPress={onPress} activeOpacity={0.8}>
      <View style={[styles.row, { backgroundColor: color ? color : colors.primary }]}>
        <Text style={styles.text}>{title}</Text>
      </View>
    </TouchableOpacity>
  )
}

Child.propTypes = {
  onPress: PropTypes.func.isRequired,
  title: PropTypes.string.isRequired,
  color: PropTypes.string.isRequired,
}

Is there a way I can reuse title and color in the prop and also pass down to the function?


Solution

  • I'm not really working with react-native. you could just pass Child into renderItem. The only issue is you need to access navigation onPress. Maybe you could use context for it.

    Theoretically this should work

    
    const Context = createContext();
    
    const Child = ({ item }) => {
      const {title, color} = item;
      const navigation = useContext(Context);
      const onPress = useCallback(() => navigation.navigate(routes.PATH, {
        title: item.name,
        foo: item.foo,
        color: item.color,
      }));
    
      return (
        <TouchableOpacity onPress={onPress} activeOpacity={0.8}>
          <View style={[styles.row, { backgroundColor: color ? color : colors.primary }]}>
            <Text style={styles.text}>{title}</Text>
          </View>
        </TouchableOpacity>
      )
    }
    
    
    const Parent = ({ navigation }) => { 
      const createChild = (item) => 
      return (
        <>
          <Context.Provider value={navigator}>
            <StatusBar hidden />
            <FlatList
              data={data}
              renderItem={Child}
              keyExtractor={item => item.id.toString()}
            />
          </Context.Provider>
        </>
      )
    }