Add colors dynamically to LinearGradient - react-native

I'm using using this data to fill a FlatList, each item contains a LinearGradient
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
firstColor: "#f472a7",
secondColor: "#d84351"
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
firstColor: "#50be71",
secondColor: "#50be71"
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
firstColor: "#e2bd4f",
secondColor: "#e49074"
}
];
I added two properties called "firstColor" and "secondColor", to fill the LinearGradient colors, but I'm having some issues doing that. I'm receiving this error:
TypeError: undefined is not an object (evaluating '_ref3.secondColor')
Code:
const Item = ({ title }, { firstColor }, { secondColor }) => (
<LinearGradient
colors={[{firstColor}, {secondColor} ]}
style={styles.item}
>
<Text style={styles.title}>{title}</Text>
</LinearGradient>
);
const renderItem = ({ item }) => (
<Item title={item.title} />
);
...
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>

Try this
const Item = ({ title, firstColor, secondColor}) => (
<LinearGradient
colors={[firstColor, secondColor ]}
style={styles.item}
>
<Text style={styles.title}>{title}</Text>
</LinearGradient>
);
const renderItem = ({ item}) => (
<Item
firstColor={item.firstColor }
secondColor={ item.secondColor }
title={item.title}
/>
);

const LinearGradient = ({ color, firstColor, secondColor }) => {
const colorArr = [firstColor, secondColor];
return (
<View>
<Text>{color}</Text>
<Text>{firstColor}</Text>
<Text>{secondColor}</Text>
</View>
);
};
can you try this, you were passing the data in the wrong way. I did some changes in similar example.

Related

Show 2 labels in FlatList React Native

I'm trying to render a flatlist that has 2 labels. I have done few options but nothing happened.
I want to show Title & Serial as Title & subtitle in each Item. If there is a solution really appreciated
Code:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
Serial: '1254'
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Items',
Serial: '5678'
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
Serial: 'XXoX'
},
];
const Item = ({ title, Serial }) => (
<TouchableOpacity style={styles.ttListButton}>
<View style={styles.TTitem}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.title}>{Serial}</Text>
</View>
</TouchableOpacity>
);
render() {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return(
<View style={{backgroundColor: '#fff'}}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</View>
)
there is a typo in ({ title, Seria })
should be ({ title, Serial })
const renderItem = ({ item }) => (
<Item title={item.title} Serial={item.Serial} />
);

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>
)
})}
/>

FlatList renderItem returning undefined

i have a flatList that renders a component with some props, but the renderItem returns me 'undefined'. I´m new to react-native and I cant´t find a solution. Thanks
edit:
Is it possible that the styles I used in 'posts.js' may affect the flatList render?
Feed.js:
export default function Feed() {
const Posts = [
{ id: 1, title: "eu", photoDesc: 'eu' },
{ id: 2, title: "me", photoDesc: 'me' }
]
console.log;
return (
<FlatList
keyExtractor={props => props.id}
data={Posts}
renderItem={({ item }) => <FeedPosts title={`${item.title}`} photoDesc={`${item.photoDesc}`} ></FeedPosts>}
>
</FlatList>
);
}
Posts.js:
export default function FeedPosts(props) {
return (
<Container>
<Header>
<TouchableOpacity>
<FontAwesome5 name='bell' size={40} style={{ marginLeft: 10 }}></FontAwesome5>
</TouchableOpacity>
<TouchableOpacity>
<Ionicons name='add-circle' size={40} style={{ marginRight: 5 }}></Ionicons>
</TouchableOpacity>
</Header>
<Body>
<Time>15/12/2021 as 17:42pm</Time>
<User>
<Icon source={require('../../assets/vibe.jpg')}></Icon>
<Description>{props.title}</Description>
</User>
<Content>
<PetPhoto source={props.postImg}></PetPhoto>
</Content>
<ContentDesc >
<PhotoDesc> {props.photoDesc}</PhotoDesc>
</ContentDesc>
<Bottom>
<Comment title="Comment" placeholder="Escrever Comentário"></Comment>
</Bottom>
<Buttons></Buttons>
</Body>
</Container>
);
}
Your variable Posts contains an array of React components. Instead, it should contain an array of data that you transform into components.
So your Posts should look more like this:
const Posts = [
{title: "My title", photoDesc: "Desc"},
{title: "My title2", photoDesc: "Desc2"},
{title: "My title3", photoDesc: "Desc3"}
]
Here's an example (straight from the React Native documentation) of how this works in context:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
(https://reactnative.dev/docs/flatlist)
You can see in the above example that DATA is an array of objects, which gets transformed with the function renderItem into components. Very similar to your use case.

React native elements Checkbox selecting multiple items using react hooks

I need a little help trying to figure this out. I am using react native elements flatlist with a checkbox inside of it. I am also using react hooks with this. Everything is working perfectly but when I try and select one of the items in the checkbox it selects all of the items. Now I have had this issue before when I was just using components and not hooks and functions. I tried to use the same method that I used here Selecting multiple items
Like this...
function ViewCategoryWS2({navigation}) {
const {category, setCategory} = useContext(ItemContext);
const [eats, setEats] = useState([]);
const [checked, toggleChecked] = useState(false);
function back() {
navigation.navigate('MenuWS2');
}
function test(index) {
const foods = category;
foods[index].checked = !foods[index].checked;
setCategory(foods);
}
return (
<View style={styles.container}>
<Icon
name='arrow-left'
color="#000000"
size={25}
style={styles.menuIcon}
onPress={back}
/>
<FlatList
data={category}
//extraData={eats}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
<CheckBox
center
titleProps={{ color: 'black', fontWeight: 'bold'}}
title={item}
iconRight
checked={checked}
onPress={() => test(index)}
size={30}
containerStyle={styles.checkBox}
/>
)}
/>
</View>
)
}
and I keep getting this error TypeError: Attempted to assign to readonly property. I have also tried it this way...
<FlatList
data={category}
//extraData={eats}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
<CheckBox
center
titleProps={{ color: 'black', fontWeight: 'bold'}}
title={item}
iconRight
checked={checked}
onPress={() => toggleChecked(!checked)}
size={30}
containerStyle={styles.checkBox}
/>
)}
/>
Here is my code from where the context is coming from. This page I pull data from my datbase and it displays categories. I click on any category and it pulls data from my database that's assigned to that certain category that was clicked on..
Here is the code...
import ItemContext from '../context/CategoryItems';
export default function menuWS({navigation}) {
const [restaurantlocationcode, setRestaurantlocationcode] = useState('')
const [menu, setMenu] = useState([]);
const {category, setCategory} = useContext(ItemContext);
const [selected, setSelected] = useState(0);
function viewMenu() {
fetch('URL', {
method: 'POST',
body: JSON.stringify({ restaurantlocationcode: restaurantlocationcode}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(response=> setMenu(response));
console.log(menu);
alert(menu);
}
function viewCategory({item}) {
fetch('URL', {
method: 'POST',
body: JSON.stringify({
category: item,
restaurantlocationcode: restaurantlocationcode,
}),
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(response => {
setCategory(response);
console.log(response);
alert(response);
});
navigation.navigate('ViewCategoryWS2', {category});
}
function showMenu() {
console.log(menu);
alert(menu);
}
const buttons = ['Menu']
return (
<View style={styles.container}>
<Input
style={styles.Input}
placeholder='Restaurant Location Code'
leftIcon={
<Icon
name='location-arrow'
size={24}
color='black'
/>
}
onChangeText={setRestaurantlocationcode}
value={restaurantlocationcode}
underlineColorAndroid='transparent'
/>
<ButtonGroup
onPress={viewMenu}
selectedIndex={selected}
selectedButtonStyle={{backgroundColor: 'blue'}}
buttons={buttons}
containerStyle={styles.buttonGroup}
/>
<FlatList
data={menu}
extraData={category}
keyExtractor={(item, index) => index.toString()}
renderItem={({item, index}) => (
<ListItem
titleStyle={{ color: 'black', fontWeight: 'bold'}}
title={item}
onPress={() => viewCategory({item})}
bottomDivider
chevron
/>
)}
/>
</View>
)
}
Here is my useContext code...
import { createContext } from 'react';
const ItemContext = createContext({});
export default ItemContext;
Here is the second part to my useContext code..
import React, {useState} from 'react';
import ItemContext from './CategoryItems';
const MenuItemState = ({children}) => {
const [category, setCategory] = useState([]);
return (
<ItemContext.Provider value={{category, setCategory}}>
{children}
</ItemContext.Provider>
)
}
export default MenuItemState;
And it just selects all of the items. I'm not sure what I am missing. Help with this would be greatly appreciated.
App Output:
import React, { useState } from 'react';
import { Text, View, StyleSheet, CheckBox, Icon, FlatList } from 'react-native';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
/*
I am using this data, but you can continue
with the one you getting from context
*/
const data = [
{ id: 1, title: 'one', checked: true },
{ id: 2, title: 'two', checked: false },
{ id: 3, title: 'three', checked: false },
{ id: 4, title: 'four', checked: false },
{ id: 5, title: 'five', checked: false },
{ id: 6, title: 'six', checked: false },
];
export default function App() {
const [category, setCategory] = useState(data);
const [eats, setEats] = useState([]);
const [checked, toggleChecked] = useState(false);
function back() {
// navigation.navigate('MenuWS2');
}
function test(index) {
/*
Use this approach while changing the state.
This will create the copy of original array,
and you can perform mutation there
and update state with it.
*/
console.log(index);
const foods = [...category];
foods[index].checked = !foods[index].checked;
setCategory(foods);
}
/*
In your Checkbox component,
use "onChange" prop instead of "onPress"
and "value" instead of "checked"
*/
return (
<View style={styles.container}>
<FlatList
data={category}
//extraData={eats}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item, index }) => (
<Card style={{ padding: 10, margin: 5 }}>
<Text>{item.title}</Text>
<CheckBox
center
titleProps={{ color: 'black', fontWeight: 'bold' }}
title={item}
iconRight
value={item?.checked}
onChange={() => test(index)}
size={30}
containerStyle={styles.checkBox}
/>
</Card>
)}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 24,
backgroundColor: 'grey',
flex: 1,
},
});
Working Example: Expo Snack

React Native, sending list through a component with withNavigation

My question is somewhat unique than many other similar ones: I want to pass some list to another screen through a (functional) component. It doesn't work.
App.js has:
const switchNavigator = createSwitchNavigator({
locationAllFlow: createStackNavigator(
{
locationsFlow: createStackNavigator(
{
Locations: { screen: LocationsScreen },
Search: { screen: SearchScreen }
},
{
headerMode: 'none'
}
),
LocationDetail: LocationDetailScreen
},
{
headerMode: 'none'
}
),
...
Then LocationsScreen has:
<TitleBar
title='Locations'
hasSearch={true}
list={results.map(result => result.name)}
/>
and LocationsScreen has TitlBar as a component:
const TitleBar = ({ navigation, title, hasSearch, list }) => {
...
<TouchableOpacity
style={{ padding: 8, position: 'absolute', right: 4 }}
onPress={() => {
console.log('inside onPress: ', list);
navigation.navigate('Search', { list });
}}
>
<MaterialIcons style={styles.titleIcon} name='search' />
</TouchableOpacity>
...
export default withNavigation(TitleBar);
and finally, need to go to SearchScreen:
const SearchScreen = ({ list }) => {
console.log('SearchScreen: list.length: ', list);
return (
<View style={{ backgroundColor: 'rgb(15, 104, 186)', flex: 1 }}>
<SafeAreaView>
<FlatList
data={list}
keyExtractor={item => item}
renderItem={({ item }) => (
<TouchableOpacity>
<Text>item</Text>
</TouchableOpacity>
)}
/>
</SafeAreaView>
</View>
);
};
Trouble happens in the SearchScreen: though inside onPress: prints list very well, somehow, SearchScreen: list.length: prints undefined. Why?
list won't be passed as params to SearchScreen. You should use navigation.getParam(paramID, defaultValue) instead
Docs reference: https://reactnavigation.org/docs/en/params.html