React Native listIem passed props - react-native

I have a question about how to pass props for one screen to another, and display the props using listItem from "React Native Elements".
First i will paste the code of the screen with the "Add Friend" form:
const addFriend = ({ navigation }) => {
const [friend, setFriend] = useState('');
const [phone, setPhone] = useState('');
return (
<View style={styles.container}>
<Input
placeholder='Friend Name'
onChangeText={friend => setFriend(friend)}
leftIcon={
<Icon
name='user'
size={24}
color='grey'
/>
}
/>
<Input
onChangeText={phone => setPhone(phone)}
placeholder='Friend Phone Number'
leftIcon={
<Icon
name='phone'
size={24}
color='grey'
/>
}
/>
<Button
title="Add Friend"
onPress={() => {
navigation.navigate('FriendList', { friend, phone })
}}
/>
</View>
);
}
Second, i will paste the screen that is suppose to show the list of friends i want to add, here i cant find the way to pass the props from the screen above, to the list:
const list = [
{
name: '',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
subtitle: ''
}
]
const FriendList = ({ route, navigation }) => {
const { friend } = route.params;
const { phone } = route.params;
return (
<View style={styles.container}>
list.map((l, i) => (
<ListItem
key={i}
leftAvatar={{ source: { uri: l.avatar_url } }}
title={l.name}
subtitle={l.subtitle}
bottomDivider
/>
))
}
{/* <Text>{JSON.stringify(friend)} {JSON.stringify(phone)}</Text> */}
</View>
);
}

You can find your parameters that you pass to your second screen in
let {friend, phone} = this.props.navigation.state.params;

Related

How to send data in previous screen with help of goBack()?

How to send data in previous screen with help of goBack() ?
I tried already. For ex: this.props.navigation.navigate('Login', {name: this.state.name})
If you simply want to pass data to the previous screen then the below works:
Parent screen:
const Parent = () => {
const [data, setData] = useState("");
let navigation = useNavigation();
const onPress = () => {
navigation.navigate('Second', { getData: (x)=>setData(x) }); //<---here you have to pass callback function
};
return (
<View style={{ flex: 1 }}>
<Button
onPress={onPress}
title="Add title here"
color="#841584"
disabled={false}
/>
<Text>{data}</Text>
</View>
);
};
Child screen:
const Child = ({ route }) => { //<------here need to take route
let navigation = useNavigation();
const onPress = () => {
let data = "John";
route.params.getData(data); //<-----this way to update.
navigation.goBack();
};
return (
<View style={{ flex: 1 }}>
<Button
onPress={onPress}
title="Add title here"
color="#841584"
disabled={false}
/>
</View>
);
};

Flatlist doesn't display the list from useContext

In react native app, I have a home screen and a second screen that the user uses to add items that should be displayed on the home screen. I am using context to save the list of items. The problem is when I add items to the second screen and go to the home screen. The displayed list is empty.
Any help to explain why this happens and how to handle it? Here's the
Data Context
export const ExpenseContext = createContext();
App.js
const Stack = createNativeStackNavigator();
function App() {
const [expenseList, setExpenseList] = useState([]);
return (
<NavigationContainer>
<ExpenseContext.Provider value={{ expenseList, setExpenseList }}>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={Home}
options={{ title: "Dashboard" }}
/>
<Stack.Screen
name="AddItem"
component={AddItem}
options={{ title: "CashFlowCreate" }}
/>
</Stack.Navigator>
</ExpenseContext.Provider>
</NavigationContainer>
);
}
export default App;
Home.js
function Home({ route, navigation }) {
const { expenseList } = useContext(ExpenseContext);
return (
<View style={styles.container}>
<Text style={styles.text}>Budget:</Text>
<Button title="+" onPress={() => navigation.navigate("AddItem")} />
<View>
<FlatList
style={styles.listContainer}
data={expenseList}
renderItem={(data) => <Text>{data.item.name}</Text>}
/>
</View>
</View>
);
}
export default Home;
AddItem.js
function AddItem({ navigation }) {
const { expenseList, setExpenseList } = useContext(ExpenseContext);
const [name, setName] = useState("");
const [amount, setAmount] = useState("");
const itemsList = expenseList;
return (
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(name) => setName( name )}
value={name}
placeholder="Name"
keyboardType="default"
/>
{name === "" && (
<Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
Name is required
</Text>
)}
<TextInput
style={styles.input}
onChangeText={(amount) => setAmount( amount )}
value={amount}
placeholder="Amount"
keyboardType="numeric"
/>
{amount === "" && (
<Text style={{ color: "red", fontSize: 12, paddingLeft: 12 }}>
Amount is required
</Text>
)}
<Button
title="Add"
style={styles.btn}
onPress={() => {
if (name === "" || amount === "") {
alert("Please Enter the required values.");
} else {
itemsList.push({
name: name,
amount: amount,
});
setExpenseList(itemsList);
}
}}
/>
<Button
title="View Dashboard"
style={styles.btn}
onPress={() => {
navigation.navigate("Home");
}}
/>
</View>
);
}
export default AddItem;
I solve it, in AddItem component remove const itemsList = expenseList; and onPress add button it should be like that instead
onPress={() => {
name === "" || amount === ""
? alert("Please Enter the required values.")
: setExpenseList([
...expenseList,
{
key:
Date.now().toString(36) +
Math.random().toString(36).substr(2),
name: name,
amount: amount,
},
]);
}}
I added the key because I needed later on.
There are several areas of issues in your code. One issue I can see is in AddItem. When you set:
const itemsList = expenseList
I think you did this for:
itemsList.push({
name: name,
amount: amount,
});
But you should look at the spread operator and try:
setExpenseList(...expenseList, {
name,
amount,
})
rewrite of AddItem.js:
function AddItem({ navigation }) {
const { expenseList, setExpenseList } = useContext(ExpenseContext)
const [name, setName] = useState('')
const [amount, setAmount] = useState('')
return (
<View style={styles.container}>
<TextInput style={styles.input} onChangeText={setName} value={name} placeholder='Name' keyboardType='default' />
{name === '' ? <Text style={styles.err}>Name is required</Text> : null}
<TextInput style={styles.input} onChangeText={setAmount} value={amount} placeholder='Amount' keyboardType='numeric' />
{amount === '' ? <Text style={styles.err}>Amount is required</Text> : null}
<Button
title='Add'
style={styles.btn}
onPress={() => {
name === '' || amount === ''
? alert('Please Enter the required values.')
: setExpenseList(...expenseList, {
name: name,
amount: amount,
})
}}
/>
<Button title='View Dashboard' style={styles.btn} onPress={() => navigation.navigate('Home')} />
</View>
)
}
export default AddItem
In your Home.js your FlatList it's missing the keyExtractor and you're trying to declare a prop of title outside of <Text>, rewrite:
function Home({ navigation }) {
const { expenseList } = useContext(ExpenseContext);
return (
<View style={styles.container}>
<Text style={styles.text}>Budget:</Text>
<Button title="+" onPress={() => navigation.navigate("AddItem")} />
<View>
<FlatList
style={styles.listContainer}
data={expenseList}
keyExtractor={(_,key) => key.toString()}
renderItem={(data) => <Text>{data.item.name}</Text>}
/>
</View>
</View>
);
}
export default Home;
Edit:
Answering to the comment. My understanding of the docs that is incorrect because keyExtractor is for identifying the id and by your commented code unless your passed in data to FlatList has a property of key then that wont work.
Also if key is not a string it should be:
keyExtractor={(item) => item.key.toString()}

ListItem not rendering data in React native

hi im trying to render some user info in my react native page and i dont know why it should render something like this:
list
but instead my output is
list
so my FlatList is working but my ListItem is no rendering any data someone could help me?
i dont know if it is a bug with reactnativeelements or so
User data
export default [
{
id: 1,
name: 'Tiago Almeida',
email: 'tiago#gmail.pt',
avatarUrl:
'https://cdn.pixabay.com/photo/2013/07/13/10/07/man-156584_960_720.png',
},
{
id: 2,
name: 'Lucas Silva',
email: 'lucas#gmail.com',
avatarUrl:
'https://cdn.pixabay.com/photo/2014/04/03/10/32/businessman-310819_960_720.png',
},
{
id: 3,
name: 'Andre Ferreira',
email: 'andre#gmail.pt',
avatarUrl:
'https://cdn.pixabay.com/photo/2018/05/19/22/03/man-3414477_960_720.png',
},];
and this is my main page
export default props => {
function getActions(user) {
return (
<>
<Button
onPress={() => props.navigation.navigate('UserForm', user)}
type='clear'
icon={<Icon name='edit' size={25} color='orange' />}
/>
</>
)
}
function getUserItem({ item: user }) {
return (
<ListItem
leftAvatar={{ source: { uri: user.avatarUrl } }}
key={user.id}
tittle={user.name}
subtitle={user.email}
bottomDivider
rightElement={getActions(user)}
onPress={() => props.navigation.navigate('UserForm', user)}
/>
)
}
return (
<View>
<FlatList
keyExtractor={user => user.id.toString()}
data={users}
renderItem={getUserItem}
/>
</View>
)
};
At the top in your imports write,
import { ListItem, Avatar } from 'react-native-elements';
After that Change your code to this
You don't need getActions
Instead write like this,
const getUserItem = ({ item: user }) => (
<ListItem
bottomDivider
onPress={() => props.navigation.navigate('UserForm', user)}>
<Avatar source={{ uri: user.avatarUrl }} />
<ListItem.Content>
<ListItem.Title>{user.name}</ListItem.Title>
<ListItem.Subtitle>{user.email}</ListItem.Subtitle>
</ListItem.Content>
<ListItem.Chevron
name="edit"
size={25}
color="orange"
onPress={() => props.navigation.navigate('UserForm', user)}
/>
</ListItem>
);
return (
<View>
<FlatList
keyExtractor={(user) => user.id.toString()}
data={users}
renderItem={getUserItem}
/>
</View>
);
Working Example here

I am trying to pass params in stack.screen but having an error

I have the following Stack.Screen in my App.js and want to access it in another screen but don't know how to do it.
App.js file: using: { id: route.params } - When I console.log(id) it returns exactly the id. Now I would like to return the same id inside the following: <Text>Edit Screen - {id}</Text>
<Stack.Screen name='ShowScreen'
component={ShowScreen}
options={({route, navigation}) => ({
title: 'Post Details',
headerRight: () => (
<TouchableOpacity onPress={() => navigation.navigate('Edit', { id: route.params })}>
<AntDesign name="edit" style={styles.iconStyle} />
</TouchableOpacity>
)
})}
/>
EditScreen.js file
import React from 'react'
import { View, Text, StyleSheet } from 'react-native'
const EditScreen = ({route}) => {
const { id } = route.params
console.log(id)
return (
<View>
<Text>Edit Screen - {}</Text>
</View>
)
}
const styles = StyleSheet.create({
//
})
export default EditScreen
Here is the Solution after two days of searching:
I just add the id after the params in the app.js as follow { id: route.params.id }
<Stack.Screen name='ShowScreen'
component={ShowScreen}
options={({route, navigation}) => ({
title: 'Post Details',
headerRight: () => (
<TouchableOpacity onPress={() => navigation.navigate('Edit', { id: route.params.id })}>
<AntDesign name="edit" style={styles.iconStyle} />
</TouchableOpacity>
)
})}
/>

react native - What should I do each time <textinput> is input, so <Google> in </NavigationContainer> cannot be re-rendered?

App.tsx
const Tab = createMaterialTopTabNavigator();
export default function App() {
const [text, setText] = useState('');
const [search, setSearch] = useState('');
const searchHandler = () => {
setSearch(text)
}
return (
<NavigationContainer>
<View style={styles.case1}></View>
<View style={styles.case1}>
<TextInput
style={styles.input}
placeholder='search'
onChangeText={(val) => setText(val)}
/>
<Button
onPress={searchHandler}
title="search button"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
<Tab.Navigator>
<Tab.Screen name="google1" component={() => <Google item={search} />} />
<Tab.Screen name="google2" component={() => <Google2 item={search} />} />
</Tab.Navigator>
</NavigationContainer>
);
}
Google.tsx
export default function google(props) {
return (
<View style={styles.webContainer}>
<WebView
source={{
uri:
'https://www.google.com/search?hl=en&sxsrf=ALeKk03BNJhsVEURZyXdlkOpk1l1qb2Nug%3A1595674787434&source=hp&ei=oxAcX4qzGLLxhwOhw5jwBA&q=' + props.item + '&oq=' +** props.item ** +'&gs_lcp=CgZwc3ktYWIQAzIFCC4QkwIyAggAMgIIADICCC4yAggAMgIIADICCAAyAggAMgIIADICCAA6BAgjECc6BQguEJECOgUIABCRAjoICC4QxwEQowI6BwguEEMQkwI6CAguEMcBEK8BUPEDWOkHYKwIaABwAHgAgAGMAYgBigOSAQMwLjOYAQCgAQGqAQdnd3Mtd2l6&sclient=psy-ab&ved=0ahUKEwjKkIXnn-jqAhWy-GEKHaEhBk4Q4dUDCAc&uact=5'
}}
/>
</View>
);
};
I'm creating an app that searches across different sites by typing in the search bar.
Whenever I type in the web-view keeps re-rendering. I only want to be re-rendered(Google web-view) when I click the search button.
I've heard that should use use-memo, Callback, as far as I know.
Thanks
const searchHandler = () => {
setSearch(text) <- "text" is a reference
}
try
const searchHandler = () => {
setSearch(`${text}`)
}
Prevent rerender WebView from props through useMemo. (memoization)
export default function google(props) {
const Web = React.useMemo(() => {
return <WebView source={{uri: 'abc'}} />
}, [])
return (
<View style={styles.webContainer}>
{Web}
</View>
);
};