FOLLOW ME: YouTube | dev.to | Twitter | Github | Medium | Reddit
Video
✅useContext ✅Use React Context to Update State in List from Detail View (React Native)
Liquid error: internal
Brief Intro
I came across a post this morning on Reddit asking about how to update state in their list from their details page. I thought this would be a good video to make, explaining how to do this in a couple of different ways. I ended up only making the video demonstrating how to use React Context to do this, which is slightly more complex code, but I feel cleaner ultimately.
Run the code in your browser: Context | Callbacks
Snack (run and tinker with code IN YOUR BROWSER 🤯 | | Reddit Post
SHUTUP, WHERES THE CODE
import React, { useState, createContext, useContext, useRef, useMemo, } from 'react'; import { StyleSheet, View, Text, SafeAreaView, TouchableOpacity, FlatList, } from 'react-native'; import { createAppContainer } from 'react-navigation'; import { createStackNavigator } from 'react-navigation-stack'; const DATA = { 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba': { id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba', title: 'First Item', selected: false, }, '3ac68afc-c605-48d3-a4f8-fbd91aa97f63': { id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63', title: 'Second Item', selected: false, }, '58694a0f-3da1-471f-bd96-145571e29d72': { id: '58694a0f-3da1-471f-bd96-145571e29d72', title: 'Third Item', selected: false, }, }; const DataContext = createContext({ data: [], selectItem: () => {}, }); const DataContextProvider = props => { const selectItem = id => { const item = state.data[id]; item.selected = !item.selected; ...state, data: { ...state.data, [item.id]: item, }, }); }; const initialState = { data: DATA, selectItem: selectItem, }; const [state, setState] = useState(initialState); return ( <DataContext.Provider value={state}>{props.children}</DataContext.Provider> ); }; const Main = ({ navigation }) => { const { data } = useContext(DataContext); return ( <SafeAreaView style={styles.container}> <FlatList data={Object.values(data)} renderItem={({ item }) => ( <Item item={item} handleShowDetails={id => { navigation.navigate('Details', { id, }); }} /> )} keyExtractor={item => item.id} /> </SafeAreaView> ); }; function Item({ item, handleShowDetails }) { const { id, title, selected } = item; const { selectItem } = useContext(DataContext); return useMemo(() => { return ( <TouchableOpacity onPress={() => { selectItem(id); }} style={[ styles.item, { backgroundColor: selected ? '#6e3b6e' : '#f9c2ff' }, ]}> <View style={{ flexDirection: 'row', justifyContent: 'space-between', padding: 18, }}> <Text style={styles.title}>{title}</Text> <Text onPress={() => handleShowDetails(id)}>Details</Text> </View> </TouchableOpacity> ); }, [selected, title]); } const Details = ({ navigation }) => { const id = navigation.state.params.id; const { data, selectItem } = useContext(DataContext); const item = data[id]; return ( <View style={[ styles.centered, { backgroundColor: item.selected ? '#6e3b6e' : '#f9c2ff' }, ]}> <Text style={styles.title}>{`Details for Item: ${item.title}`}</Text> <Text onPress={() => { selectItem(item.id); }}>{`Is selected: ${item.selected}\n\n(click me to toggle selected)`}</Text> </View> ); }; const StackNavigation = createStackNavigator({ Main: Main, Details: Details, }); const Container = createAppContainer(StackNavigation); const App = () => ( <DataContextProvider> <Container /> </DataContextProvider> ); export default App; const styles = StyleSheet.create({ centered: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 16, }, title: { fontSize: 32, fontWeight: '400', }, container: { flex: 1, marginTop: 24, }, item: { backgroundColor: '#f9c2ff', padding: 20, marginVertical: 8, marginHorizontal: 16, }, });
🤟🙏 THANKS FOR READING 🤟🙏
If you liked the post, please be sure to give it a thumbs up, a heart, an upvote, a retweet, or whatever it is that the cool kids do these days. All my follow links are below if you're intersted in quick tutorials and explanations like this one.
🤔 QUESTIONS | 📝 COMMENTS | 📉 CONCERNS | 📩 SUGGESTIONS
Let me know if you have any questions in the comments or if I could have done a better job explaining anything anywhere.
Most importantly,
💻📲👨🏻💻KEEP CODING, KEEP LEARNING, AND KEEP DOING!
Top comments (2)
Hey Michael, great article! I was wondering how you would have implemented the feature to add another object to DATA, and have it update the list. Would it be possible to do this without re-rendering the whole DATA?
Thanks a lot! Adding another data item to DATA should already work without re-rendering the rest of the Components in the list because within the render method of the list item, we're using useMemo and only re-rendering those when title or selected changes.
Try modifying the example and let me know if you run into any issues.