How to change input value using setState - javascript

i'm building a simple todo app, and i need to change the input value ( to edit tasks ). I tried to make it like in the react native docs :
export default function UselessTextInput() {
const [value, onChangeText] = React.useState('Useless Placeholder');
return (
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={text => onChangeText(text)}
value={value}
/>
);
}
But in my code i have my input inside map function and it displays an error : "undefined is not a function ( near '...todos.tasks.map...')
Can anyone explain me why do I get this error and how to solve it ?
My code :
const App = () => {
const[todos,setTodos] = useState({
tasks: [],
task: '',
key: ''
})
const addItem = () => {
if(todos.task != '' && todos.task != null){
setTodos({
tasks: todos.tasks.concat(todos.task),
task: ''
})
console.log(todos.tasks)
}
else {
Alert.alert('OOPS!', 'You need to fill in input' , [{
text: 'Understood'
}])
}
}
const removeItem = arg => {
const list = todos.tasks;
list.splice(arg,1)
setTodos({tasks: list})
}
const handleInputTextChange = (newText) => {
setTodos({
tasks: newText
})
}
return (
<ScrollView keyboardShouldPersistTaps='handled'>
<View style={styles.container}>
<View style = {styles.header}>
<Text style = {styles.title}>Todos</Text>
</View>
<View style={styles.content}>
<TextInput
style = {styles.input}
placeholder = "Type new item"
value = {todos.task}
onChangeText = {e => setTodos({...todos, task: e, key: Date.now()})}
/>
<ButtonSubmit text = 'Submit' onPress = {addItem}/>
{
todos.tasks.map((item, index) => {
return(
<TouchableOpacity>
<View style = {styles.Wrapper} key = {todos.key}>
<View style = {styles.taskWrapper}>
<TextInput style = {styles.task} id = {todos.key} value = {item} onChangeText={handleInputTextChange} />
</View>
<ButtonRemove onPress = {() => removeItem(index)} />
</View>
</TouchableOpacity>
)
})
}
</View>
</View>
</ScrollView>
);
}

You are overwriting your tasks array with the input value and then you get an error when trying to map tasks that is a string and not an array anymore.
Try this:
const App = () => {
const[todos,setTodos] = useState({
tasks: [],
task: '',
key: ''
})
const addItem = () => {
if(todos.task != '' && todos.task != null){
setTodos({
tasks: todos.tasks.concat(todos.task),
task: ''
})
console.log(todos.tasks)
}
else {
Alert.alert('OOPS!', 'You need to fill in input' , [{
text: 'Understood'
}])
}
}
const removeItem = arg => {
const list = todos.tasks;
list.splice(arg,1)
setTodos({tasks: list})
}
const handleInputTextChange = (newText, index) => {
setTodos((s) => {
...s,
tasks: s.tasks.map((t, i) => i === index ? newText : t)
})
}
return (
<ScrollView keyboardShouldPersistTaps='handled'>
<View style={styles.container}>
<View style = {styles.header}>
<Text style = {styles.title}>Todos</Text>
</View>
<View style={styles.content}>
<TextInput
style = {styles.input}
placeholder = "Type new item"
value = {todos.task}
onChangeText = {e => setTodos({...todos, task: e, key: Date.now()})}
/>
<ButtonSubmit text = 'Submit' onPress = {addItem}/>
{
todos.tasks.map((item, index) => {
return(
<TouchableOpacity>
<View style = {styles.Wrapper} key = {todos.key}>
<View style = {styles.taskWrapper}>
<TextInput style = {styles.task} id = {todos.key} value = {item} onChangeText={value => handleInputTextChange(value, index)} />
</View>
<ButtonRemove onPress = {() => removeItem(index)} />
</View>
</TouchableOpacity>
)
})
}
</View>
</View>
</ScrollView>
);
}
Also, check your code for using key prop as it appears to be problematic. You should never use Date.now() as a key. Check React docs:
https://reactjs.org/docs/lists-and-keys.html

Related

How to edit item in a Flatlist

I made a Flatlist and and edit button that can open a modal to a text input and track down the key of the specific item. How do I update this item in the Flatlist with the different text input. I tried doing something with the setJournal but I don't know how to return it with the edited entry.
export default function HomeScreen({ navigation }) {
const [journal, setJournal] = useState([
{ date: "12-dec22", entry: "good day", key: "1" },
{ date: "12-dec22", entry: "bad day", key: "2" },
]);
const [editModal, setEditModal] = useState(false);
const handleEditPress = (key) => {
const currentJournal = journal.find((journn) => {
return journn.key === key;
});
setEditModal(true);
console.log(key);
};
const updateEntry = (key, entry) => {
if (journal.key === key) {
setJournal((currentJournal) => {
return [entry, ...currentJournal];
});
} else {}
journal = journal.map((journn) =>
journn.key === key ? { ...journn, ...updateEntry } : journn
);
};
return (
<View>
<Modal visible={editModal}>
<TextInput onChangeText={() => updateEntry()} />
<MaterialIcons name="close" onPress={() => setEditModal(false)} />
</Modal>
<View>
<MaterialIcons onPress={() => setModalOpen(true)}/>
<MaterialIcons onPress={() => deleteAll()} />
</View>
<FlatList
data={journal}
renderItem={({ item }) => (
<View style={styles.flatlistView}>
<TouchableOpacity>
<View>
<MaterialIcons onPress={() => handleEditPress(item.key)}/>
</View>
</TouchableOpacity>
</View>
)}
/>
</View>
);
}
const handleEditPress = (editedField, itemKey)=>{
journal.filter((currentItem.key)=>{(currentItem.key) === itemKey})).text = editedField
setJournal(journal)
}

ReactNative rerenders component when the user opens the page

I have two components the first where user can add a place to the favorites and the second is favorites component where user may see all his favorite places. When the user for the first time opens the favorites component everything works as expected: all the favorite places that user has already added to the favorites rendered. But if user go to the first component and add one more place and then go to the second component new place will not appear because component has already rendered and the state didn't changed because useEffect not triggered. Help me please what should I use in my FavouritePlaces component instead of useEffect to rerender this component every time when user open FavouritePlaces?
Component where user can add to favorites:
const ModalWindow = ({navigateToPlace, sendDataToParent, visible, marker}: HomeNavigationProps<"ModalWindow">) => {
const regex = /(<([^>]+)>)|( )|(&nbps)/ig;
const result = marker.description.replace(regex, '');
const [favKeys, setFavKeys] = useState([]);
const onDismiss = () => {
sendDataToParent(false)
}
const onNavigationTap = () => {
onDismiss();
navigateToPlace(true, marker.coordinates);
}
const getFavourites = async () => {
let keys = []
keys = await AsyncStorage.getAllKeys()
setFavKeys(keys);
}
const onHeartPress = async () => {
const jsonValue = JSON.stringify(marker)
try {
if (favKeys.includes(marker.id.toString())){
await AsyncStorage.removeItem(marker.id.toString())
await getFavourites();
} else {
await AsyncStorage.setItem(marker.id.toString(), jsonValue)
await getFavourites();
}
} catch (e) {
console.log('error in onHeartPress', e)
}
console.log('Done.')
//remove after test
try {
await AsyncStorage.removeItem('__react_native_storage_test')
} catch(e) {
// remove error
}
console.log('Done.')
}
return (
<Modal visible={visible} onDismiss={onDismiss} contentContainerStyle={styles.container}>
<IconButton
style={
styles.iconButton
}
icon="close"
color={Colors.black}
size={30}
onPress={() => onDismiss()}
/>
<Text
style={{fontStyle: "italic", fontSize: 20, alignSelf: "center", maxWidth: '75%'}}>{marker.title}
</Text>
<CustomCarousel {...{marker}} />
<ScrollView showsVerticalScrollIndicator={false} style={{marginTop: '3%', marginLeft: '3%', marginRight: '3%'}}>
<Text>{result}</Text>
</ScrollView>
<View style={{flexDirection: "row", justifyContent: "space-around", marginLeft: "3%", marginRight: "3%", marginBottom: "15%"}}>
<TouchableOpacity onPress={() => onNavigationTap()}>
<View style={{flexDirection: "row", alignItems: "center"}}>
<Ionicons size={height/20} name={'navigate-circle-outline'} />
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => onHeartPress()}>
{marker.id ?
<View style={{flexDirection: "row", alignItems: "center"}}>
{favKeys.includes(marker.id.toString()) ? <Ionicons size={height/20} name={'heart-dislike'} /> : <Ionicons size={height/20} name={'heart'} />}
</View> : undefined}
</TouchableOpacity>
</View>
</Modal>
);
}
export default ModalWindow;
My Favorite Places component:
const FavouritePlaces = ({navigation}: HomeNavigationProps<"FavouritePlaces">) => {
const [markers, setMarkers] = useState([]);
useEffect(() => {
const getFavourites = async () => {
let keys = []
try {
keys = await AsyncStorage.getAllKeys()
} catch (e) {
// read key error
}
let values
try {
let forDeletion = ['__react_native_storage_test', 'NAVIGATION_STATE_KEY-40.0.0'];
keys = keys.filter(item => !forDeletion.includes(item))
values = await AsyncStorage.multiGet(keys)
setMarkers(values)
} catch (e) {
// read error
}
}
getFavourites();
}, [])
const transition = (
<Transition.Together>
<Transition.Out type='fade'/>
<Transition.In type='fade'/>
</Transition.Together>
);
const list = useRef<TransitioningView>(null);
const theme = useTheme()
const width = (wWidth - theme.spacing.m * 3) / 2;
const [footerHeight, setFooterHeight] = useState(0);
return (
<Box flex={1} backgroundColor="background">
<StatusBar style="black" />
<Header
title="Избранные места"
left={{icon: 'menu', onPress: () => navigation.openDrawer()}}
right={{icon: 'shopping-bag', onPress: () => true}}
/>
<Box flex={1}>
<ScrollView showsVerticalScrollIndicator={false} contentContainerStyle={{
paddingBottom: footerHeight,
}}>
<Transitioning.View ref={list} transition={transition} style={{}}>
{markers ?
<Box flexDirection='row' style={{justifyContent: "space-around"}}>
<Box>
{markers
.filter((_, i) => i % 2 === 0).map((currentMarker) => <Picture
key={currentMarker}
place={currentMarker}
width={width}
height={height}
/>)}
</Box>
<Box>
{markers
.filter((_, i) => i % 2 !== 0).map((currentMarker) => <Picture
key={currentMarker}
place={currentMarker}
width={width}
height={height}/>)}
</Box>
</Box> : undefined}
</Transitioning.View>
</ScrollView>
{/*<TopCurve footerHeight={footerHeight}/>*/}
<Box position='absolute' bottom={0} left={0} right={0} onLayout={({
nativeEvent: {
layout: {height},
}
}) => setFooterHeight(height)}>
</Box>
</Box>
</Box>
)
}
export default FavouritePlaces
Try this
useEffect(() => {
// ... Your code goes here
}, [navigation]);
this will render whenever update in navigate
I've found the solution. React navigation has hook useIsFocused, so what can we do is:
import { useIsFocused } from "#react-navigation/native";
const isFocused = useIsFocused();
useEffect(() => {
// ... Your code goes here
}, [isFocused]);
You can use React Context API to share the state across the screens.
Check out this Expo Snack I created.
import {
CompositeNavigationProp,
NavigationContainer,
NavigatorScreenParams,
} from '#react-navigation/native';
import {
createStackNavigator,
StackNavigationProp,
} from '#react-navigation/stack';
import * as React from 'react';
import {
Button,
FlatList,
ListRenderItem,
Text,
TextInput,
View,
} from 'react-native';
type MainStackParamsList = {
FavoritePlacesScreen: undefined;
};
type ModalStackParamsList = {
MainStack: NavigatorScreenParams<MainStackParamsList>;
AddFavoritePlacesModal: undefined;
};
type FavoritePlace = {
id: number;
name: string;
};
type FavoritePlacesContextValue = {
favoritePlaces: FavoritePlace[];
addNewFavoritePlace: (favoritePlace: FavoritePlace) => void;
removeFavoritePlace: (id: number) => void;
};
const FavoritePlacesContext = React.createContext<FavoritePlacesContextValue>({
favoritePlaces: [],
addNewFavoritePlace: () => {},
removeFavoritePlace: () => {},
});
const MainStack = createStackNavigator<MainStackParamsList>();
type FavoritePlacesScreenProps = {
navigation: CompositeNavigationProp<
StackNavigationProp<MainStackParamsList, 'FavoritePlacesScreen'>,
StackNavigationProp<ModalStackParamsList>
>;
};
const FavoritePlacesScreen = ({navigation}: FavoritePlacesScreenProps) => {
const {favoritePlaces, removeFavoritePlace} = React.useContext(
FavoritePlacesContext,
);
const renderItem = React.useCallback<ListRenderItem<FavoritePlace>>(
({item}) => {
return (
<View style={{height: 50, padding: 10, flexDirection: 'row'}}>
<Text style={{fontSize: 16}}>{item.name}</Text>
<Button onPress={() => removeFavoritePlace(item.id)} title="Remove" />
</View>
);
},
[removeFavoritePlace],
);
return (
<View style={{flex: 1}}>
<FlatList
data={favoritePlaces}
keyExtractor={(item) => String(item.id)}
renderItem={renderItem}
/>
<Button
onPress={() => {
navigation.navigate('AddFavoritePlacesModal');
}}
title="Add new favorite"
/>
</View>
);
};
const MainStackNavigator = () => {
return (
<MainStack.Navigator>
<MainStack.Screen
component={FavoritePlacesScreen}
name="FavoritePlacesScreen"
/>
</MainStack.Navigator>
);
};
type AddFavoritePlacesModalProps = {
navigation: StackNavigationProp<
ModalStackParamsList,
'AddFavoritePlacesModal'
>;
};
const AddFavoritePlacesModal = ({navigation}: AddFavoritePlacesModalProps) => {
const {addNewFavoritePlace} = React.useContext(FavoritePlacesContext);
const [favoritePlaceName, setFavoritePlaceName] = React.useState('');
const handleOnSave = React.useCallback(() => {
addNewFavoritePlace({
id: Date.now(),
name: favoritePlaceName,
});
navigation.goBack();
}, [addNewFavoritePlace, favoritePlaceName, navigation]);
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<View style={{borderRadius: 6, borderWidth: 1, borderColor: '#333'}}>
<TextInput
onChangeText={setFavoritePlaceName}
placeholder="Name your favorite place"
/>
</View>
<Button onPress={handleOnSave} title="Save" />
</View>
);
};
// Put the favorite places list screen and the add favorite place modal here.
// Then use FavoritePlacesContext.Provider to wrap ModalStack.Navigator in order
// for the context to be available on MainStack
const ModalStack = createStackNavigator<ModalStackParamsList>();
const ModalNavigator = () => {
const [favoritePlaces, setFavoritePlaces] = React.useState<FavoritePlace[]>(
[],
);
const addNewFavoritePlace = React.useCallback(
(favoritePlace: FavoritePlace) => {
setFavoritePlaces((prev) => [...prev, favoritePlace]);
},
[],
);
const removeFavoritePlace = React.useCallback((id: number) => {
setFavoritePlaces((prev) =>
prev.filter((favoritePlace) => favoritePlace.id !== id),
);
}, []);
return (
<FavoritePlacesContext.Provider
value={{
favoritePlaces,
addNewFavoritePlace,
removeFavoritePlace,
}}
>
<ModalStack.Navigator headerMode="none">
<ModalStack.Screen component={MainStackNavigator} name="MainStack" />
<ModalStack.Screen
component={AddFavoritePlacesModal}
name="AddFavoritePlacesModal"
options={{headerShown: false}}
/>
</ModalStack.Navigator>
</FavoritePlacesContext.Provider>
);
};
const App = () => {
return (
<NavigationContainer>
<ModalNavigator />
</NavigationContainer>
);
};
export default App;

Failed prop type: Invalid prop `defaultValue` of type `object`

Hy! I'm new in react native but I'm facing this issue.
I design the OTP screen using TextInput but having that error I don't know why, failed prop type invalid prop 'defaultValue' of type 'object' supplied to 'textinput' expected 'string'.
I used state hook and useref hook to do create this screen.
here's complete code of screen:
//import files
const EmailOTP = ({ navigation }) => {
const [otpState, setOtpState] = useState({
pin1: '',
pin2: '',
pin3: '',
pin4: '',
pin5: '',
pin6: '',
})
otpState.pin1 = useRef('');
otpState.pin2 = useRef('');
otpState.pin3 = useRef('');
otpState.pin4 = useRef('');
otpState.pin5 = useRef('');
otpState.pin6 = useRef('');
useEffect(() => {
otpState.pin1.current.focus();
}, [])
return (
<View style={styles.container} >
<ScrollView
contentInsetAdjustmentBehavior="automatic"
showsVerticalScrollIndicator={false}
>
<View style={styles.OTPWrapper} >
<TextInput
ref={otpState.pin1}
onChangeText={pin1 => {
setOtpState({ pin1: pin1 })
if (otpState.pin1 != "") {
otpState.pin2.current.focus();
}
}
}
defaultValue={otpState.pin1}
maxLength={1}
style={styles.OTPinput}
/>
<TextInput
ref={otpState.pin2}
onChangeText={pin2 => {
setOtpState({ pin2: pin2 })
if (otpState.pin2 != "") {
otpState.pin3.current.focus();
}
}
}
defaultValue={otpState.pin2}
maxLength={1}
style={styles.OTPinput}
/>
<TextInput
ref={otpState.pin3}
onChangeText={pin3 => {
setOtpState({ pin3: pin3 })
if (otpState.pin3 != "") {
otpState.pin4.current.focus();
}
}
}
defaultValue={otpState.pin3}
maxLength={1}
style={styles.OTPinput}
/>
<TextInput
ref={otpState.pin4}
onChangeText={pin4 => {
setOtpState({ pin4: pin4 })
if (otpState.pin4 != "") {
otpState.pin5.current.focus();
}
}
}
defaultValue={otpState.pin4}
maxLength={1}
style={styles.OTPinput}
/>
<TextInput
ref={otpState.pin5}
onChangeText={pin5 => {
setOtpState({ pin5: pin5 })
if (otpState.pin5 != "") {
otpState.pin6.current.focus();
}
}
}
defaultValue={otpState.pin5}
maxLength={1}
style={styles.OTPinput}
/>
<TextInput
ref={otpState.pin6}
onChangeText={pin6 => {
setOtpState({ pin6: pin6 })
}
}
defaultValue={otpState.pin6}
maxLength={1}
style={styles.OTPinput}
/>
</View>
<TouchableOpacity onPress={()=>navigation.navigate('PhoneNumberVerification')}>
<View style={[styles.btnWrapper, { marginTop: 40, }]} >
<Text style={styles.logButton} >Verify Email</Text>
</View>
</TouchableOpacity>
<View style={styles.contentWrapperOtpResend} >
<View style={styles.loginRedirectWrapper}>
<Text style={styles.loginRedirectText} >Didn't Receive the code?</Text>
<Text style={styles.loginRedirectButton}> Resend</Text>
</View>
</View>
</ScrollView>
</View>
);
}
export default EmailOTP
The way I see it, you actually have just linked the pins but have not set them. Try this instead:
otpState.pin1 = useRef(null);
otpState.pin2 = useRef(null);
otpState.pin3 = useRef(null);
otpState.pin4 = useRef(null);
otpState.pin5 = useRef(null);
otpState.pin6 = useRef(null);
otpState.pin1.current = '';
otpState.pin2.current = '';
otpState.pin3.current = '';
otpState.pin4.current = '';
otpState.pin5.current = '';
otpState.pin6.current = '';
And set the defaultValue of every TextInput to their respective pins like this : 'otpState.pin1.current'
This is how the TextInput should look like:
<TextInput
ref={otpState.pin1}
onChangeText={pin1 => {
setOtpState({pin1: pin1});
if (otpState.pin1 != '') {
otpState.pin2.current.focus();
}
}}
defaultValue={otpState.pin1.current}
maxLength={1}
style={styles.OTPinput}
/>

How to add multiple items to a flatlist using textinput?

i'm trying to add items to a flatlist via textinput. at the moment i can only add one item and when i try to add a second it just updates the first item, although the data from the textinput should appear below the previous textinput. i have found a few instances of a similar kind of problem and i know that i probably need to add something to my code but i just can't figure out what. below is my code. i would be grateful for any kind of help :)
function FlatlistComponent({ }) {
const listItems = [];
const [arrayHolder, setArrayHolder] = React.useState([]);
const [textInputHolder, setTextInputHolder] = React.useState('');
useEffect(() => {
setArrayHolder(listItems)
}, [])
const joinData = () => {
listItems.push({ name : textInputHolder });
setArrayHolder(listItems);
}
const FlatListItemSeparator = () => {
return (
<View
style={{
height: 1,
width: "95%",
backgroundColor: '#00678A',
alignSelf: 'center'
}} />
);
}
// Delete note
deleteNote = id => () => {
const filteredData = arrayHolder.filter(item => item.id !== id);
setArrayHolder({ data: filteredData });
}
return (
<View style={styles.MainContainer}>
<FlatList
data={arrayHolder}
width='100%'
extraData={arrayHolder}
keyExtractor={(item) => item.id}
ItemSeparatorComponent={FlatListItemSeparator}
renderItem={({ item }) => <Text style={styles.item} onPress={deleteNote(item.id)}> {item.name} </Text>}
/>
<TextInput
placeholder='Kirjoita uusi'
onChangeText={data => setTextInputHolder(data)}
style={styles.textInputStyle}
underlineColorAndroid='transparent'
clearTextOnFocus={true}
value={listItems}
/>
<TouchableOpacity onPress={joinData} style={styles.button} >
<Text style={styles.buttonText}> + </Text>
</TouchableOpacity>
</View>
);
}
listItems is always an empty array after component re-rendered, you should concat previous arrayHolder with new item:
const joinData = () => {
setArrayHolder([... arrayHolder, {name: textInputHolder }]);
// or use update function
// setArrayHolder(prev => [...prev, {name: textInputHolder }]);
}

How to pass props to FlatList with renderScene in react-native-tab-view?

I'm a newbie in React Native and trying to pass props to ListHeaderComponent in FlatList
Here's the code:
const FirstRoute = (props) => {
const _renderHeader = () => {
return(
<View>
{props.isFollowed &&
<TouchableOpacity onPress={props.onSubmit}>
<Text>You have followed this person</Text>
</TouchableOpacity> }
</View>
)
}
return(
<View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
<FlatList
data={data}
keyExtractor={item => item.id}
renderItem={itemData => ( <Image source={itemData.item.id} style={{height: WIDTH/3, width: WIDTH/3}} />)}
ListHeaderComponent={_renderHeader}
/>
</View>
)
};
const SecondRoute = () => (
<View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);
const initialLayout = { width: Dimensions.get('window').width };
export default function Parent() {
const [index, setIndex] = React.useState(0);
const [routes] = useState([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
const [_isFollowed, setIsFollowed] = useState(false);
const _onSubmit = () => {
...
setIsfollowed(true)
}
const renderScene = ({route}) => {
switch(route.key){
case 'first': return <FirstRoute {...props} onSubmit={_onSubmit} isFollowed={_isFollowed} />
case 'second': return <SecondRoute {...props} />
}
};
return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
/>
);
}
But when I save it, the screen logs the error: Can't find the value of isFollowed
I think the problem is at the way I pass the props. I'm still learning it. Since when I delete the ListHeaderComponent, the FlatList still generates the list of images well. And I don't know if it has something to do with renderScene
I really don't understand why
Please help me. Thank you very much
Let me get this straight. You need to render _renderHeader dinamically based on _isFollowed state. So, you passed to the first route as props your _onSubmit function and _isFollowed state in order to get to access them at _renderHeader. Right?
As I see you actually doesn't need to do it once your _renderHeader has direct access to both _isFollowed state and _onSubmit function. Try it out as bellow:
export default function Parent() {
const [index, setIndex] = React.useState(0);
const [routes] = useState([
{ key: 'first', title: 'First' },
{ key: 'second', title: 'Second' },
]);
const [_isFollowed, setIsFollowed] = useState(false);
const initialLayout = { width: Dimensions.get('window').width };
function _onSubmit() {
setIsFollowed(true);
}
function _renderHeader() {
return (
<View>
{_isFollowed &&
<TouchableOpacity onPress={_onSubmit}>
<Text>You have followed this person</Text>
</TouchableOpacity> }
</View>
);
}
const FirstRoute = () => {
return(
<View style={[styles.scene, { backgroundColor: '#ff4081' }]}>
<FlatList
data={data}
keyExtractor={item => item.id}
renderItem={itemData => ( <Image source={itemData.item.id} style={{height: WIDTH/3, width: WIDTH/3}} />)}
ListHeaderComponent={_renderHeader}
/>
</View>
)
};
const SecondRoute = () => (
<View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);
const renderScene = ({route}) => {
switch(route.key){
case 'first': return <FirstRoute />
case 'second': return <SecondRoute />
}
};
return (
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
onIndexChange={setIndex}
initialLayout={initialLayout}
/>
);
}
Other point I don't understand in your code and couldn't check cause I didn't try to run it was the function bellow:
function _renderHeader() {
return (
<View>
{_isFollowed &&
<TouchableOpacity onPress={_onSubmit}>
<Text>You have followed this person</Text>
</TouchableOpacity> }
</View>
);
}
If you want to render TouchableOpacity just in case _isFollowed is true you should do it using ternary operator like so:
function _renderHeader() {
return (
<View>
{_isFollowed ?
<TouchableOpacity onPress={_onSubmit}>
<Text>You have followed this person</Text>
</TouchableOpacity> }
: <></>
}
</View>
);
}

Categories

Resources