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.