I'd created custom radio boxes like as shown below.
But I want to make like as the first one should default selected like as shown below:
Here is the full code for this:
function Chips({ data, onSelect }) {
const [userOption, setUserOption] = useState(null);
const selectHandler = (value) => {
onSelect(value);
setUserOption(value);
};
return (
<View style={{flexDirection: "row"}}>
{data.map((item) => {
return (
<Pressable
style={[item.value === userOption ? styles.selected : styles.unselected, styles.commonChips]}
onPress={() => selectHandler(item.value)}>
<Text style={{color: item.value === userOption ? '#fff' : '#bfccd3', fontWeight: "bold"}}>{item.value}</Text>
</Pressable>
);
})}
</View>
);
}
export default function App(){
return (
<Chips data={data} onSelect={(value) => setOption(value)} />
)
}
You can set the default value while declaring state
const [userOption, setUserOption] = useState(data[0].value);
Related
There is example https://reactnative.dev/docs/flatlist
Let's say I want to add button in each flatlist item. All happens inside App.js
const Item = ({ item,.....}) => (
<TouchableOpacity onPress={onPress} style={..}>
<Button title='Go' onPress={() => myFunc('abc')} /> </TouchableOpacity>);
const App = () => {
function myFunc(x){
}
}
I get " ReferenceError: Can't find variable: myFunc "
I solved this by moving Item inside of const App = () => { but I think it might be wrong.
Tell me please, what is the correct way?
You could do something like this:
const App = () => {
const myFunc = (args) => {
// perform your action here.
}
return (
<FlatList
data={[{ title: 'Title Text', key: 'item1' }]}
renderItem={({ item, index, separators }) => (
<TouchableOpacity
key={item.key}
onPress={() => myFunc('abc')}
>
<View style={{ backgroundColor: 'white' }}>
<Text>{item.title}</Text>
</View>
</TouchableOpacity>
)}
/>
)
}
export default App;
Also you do not need to using TouchableOpacity if you are using Button Component already.
And since you are using separate component to render item for FlatList so it can be done as below:
// Considering App as Parent Component
const App = () => {
// Considering Item as separate Component
const Item = ({item, index, separators}) => {
return (
<TouchableOpacity
key={item.key}
onPress={() => myFunc('abc')}
>
<View style={{ backgroundColor: 'white' }}>
<Text>{item.title}</Text>
</View>
</TouchableOpacity>
)
}
const myFunc = (args) => {
// perform your action here.
}
return (
<FlatList
data={[{ title: 'Title Text', key: 'item1' }]}
renderItem={Item}
/>
)
}
export default App;
All code are inside App Component;
I want to use toggle with map function.
I've tried many things, but I returned to the first code. I know what's the problem(I use the map function, but I use only one toggle variable), but I don't know how to fix it.
This is my code.
const [toggle, setToggle] = useState(true);
const toggleFunction = () => {
setToggle(!toggle);
};
{wholeData.map((image)=>{
return(
<TouchableOpacity
key={image.ROWNUM}
onPress={() => navigation.navigate("DetailStore", {
contents: image,
data: wholeData
})}
>
.
.
.
<TouchableOpacity onPress={() => toggleFunction()}>
{toggle ? (
<View style={{marginRight: 11}}>
<AntDesign name="hearto" size={24} color="#C7382A" />
</View>
) : (
<View style={{marginRight:11}}>
<AntDesign name="heart" size={24} color="#C7382A" />
</View>
)}
</TouchableOpacity>
As you've noticed, using a single state for all the toggles won't give you what you want. All you have to do is move your toggle function inside the component you return when you're mapping over your images.
As an unrelated note, you could also simplify your second TouchableOpacity a bit, since the only thing that changes is the icon name.
For example:
// New component
const ListImage = ({ image }) => {
const [toggle, setToggle] = useState(true);
const toggleFunction = () => {
setToggle(!toggle);
};
return (
<TouchableOpacity
key={image.ROWNUM}
onPress={() => navigation.navigate("DetailStore", {
contents: image,
data: wholeData
})}
>
...
<TouchableOpacity onPress={() => toggleFunction()}>
<View style={{ marginRight: 11 }}>
<AntDesign
name={toggle ? "hearto" : "heart"}
size={24}
color="#C7382A"
/>
</View>
</TouchableOpacity>
)
}
// in current component
{wholeData.map((image) => {
return <ListImage image={image} />
})}
I'm really new to React Native and I'm wondering how can I hide/show View
Here's my test code:
class Counter extends React.Component{
state = { count:0 };
setCount = () => this.setState(
prevState => ({ ...prevState, count: this.state.count + 1 })
)
render(){
const { count } = this.state;
const [valueLocation, onChangeText] = React.useState('Pleas input Address');
const [value, onChangeEvent] = React.useState('Your questions');
return (
<ScrollView style={styles.header}>
<View style={styles.box1}>
<View style={styles.box2}>
<View style={styles.user}>
<Image
style={styles.userImg}
source={{
uri: event.user[0].image,
}}
/>
<View style={styles.userText}>
<Text style={styles.username}>{event.user[0].name}</Text>
<Text style={styles.date}>{event.user[0].date}</Text>
</View>
</View>
<View style={styles.boxHidebtn}>
<View style={styles.EventClass}>
<Text style={styles.btn_text_white}>類型</Text>
</View>
<TouchableOpacity
style={styles.EventOpen}
onPress={this.setCount}
>
<Text>></Text>
</TouchableOpacity>
</View>
</View>
<View style={count % 2 ? styles.box3 : styles.box3Open}>
<Text style={styles.address}>台北市市民大道六段37號</Text>
<Text style={styles.eventShow}>路上坑洞造成積水</Text>
</View>
</View>
</ScrollView>
);
}
}
const App = () => {
<Counter/>
};
const styles = StyleSheet.create({
....
});
export default App;
I run my code and it tell me
"App(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
thanks!!!!!!!!
It looks like your arrow function needs to return the Counter:
const App = () => {
return <Counter/>;
};
Or, simply:
const App = () => <Counter/>;
I can see three errors in your code:
const App = () => {
return <Counter/>; // here you should return Counter
};
prevState -> this.state I guess
setCount = () => this.setState({ ...this.state, count: this.state.count + 1 }); // here
you have also a syntax error <Text>></Text> remove this extra closing > inside touchableopacity
Regarding your question in the title? I can't see where you want to hide the view?
I want a text input box and it should show suggestions while typing, if there are no suggestions it should take the typed input, otherwise it should take input from the suggestion array. How can I achieve this?
I have gone through few documents and modules react-native-autocomplete-input but could not understand the code. Can anyone help me out.
You can also build your own like below. This way you will have more control over the component and modify the behavior.
In this example I am using https://callstack.github.io/react-native-paper/text-input.html
// Autocomplete/index.js
import { View } from "react-native";
import { Menu, TextInput } from "react-native-paper";
import { bs } from "../../styles";
import React, { useState } from "react";
const Autocomplete = ({
value: origValue,
label,
data,
containerStyle,
onChange: origOnChange,
icon = 'bike',
style = {},
menuStyle = {},
right = () => {},
left = () => {},
}) => {
const [value, setValue] = useState(origValue);
const [menuVisible, setMenuVisible] = useState(false);
const [filteredData, setFilteredData] = useState([]);
const filterData = (text) => {
return data.filter(
(val) => val?.toLowerCase()?.indexOf(text?.toLowerCase()) > -1
);
};
return (
<View style={[containerStyle]}>
<TextInput
onFocus={() => {
if (value.length === 0) {
setMenuVisible(true);
}
}}
// onBlur={() => setMenuVisible(false)}
label={label}
right={right}
left={left}
style={style}
onChangeText={(text) => {
origOnChange(text);
if (text && text.length > 0) {
setFilteredData(filterData(text));
} else if (text && text.length === 0) {
setFilteredData(data);
}
setMenuVisible(true);
setValue(text);
}}
value={value}
/>
{menuVisible && filteredData && (
<View
style={{
flex: 1,
backgroundColor: 'white',
borderWidth: 2,
flexDirection: 'column',
borderColor: 'grey',
}}
>
{filteredData.map((datum, i) => (
<Menu.Item
key={i}
style={[{ width: '100%' }, bs.borderBottom, menuStyle]}
icon={icon}
onPress={() => {
setValue(datum);
setMenuVisible(false);
}}
title={datum}
/>
))}
</View>
)}
</View>
);
};
export default Autocomplete;
Usage
<Autocomplete
value={'Honda'}
style={[style.input]}
containerStyle={[bs.my2]}
label="Model"
data={['Honda', 'Yamaha', 'Suzuki', 'TVS']}
menuStyle={{backgroundColor: 'white'}}
onChange={() => {}}
/>
<Autocomplete
autoCapitalize="none"
autoCorrect={false}
containerStyle={styles.autocompleteContainer}
//data to show in suggestion
data={films.length === 1 && comp(query, films[0].title) ? [] : films}
//default value if you want to set something in input
defaultValue={query}
/*onchange of the text changing the state of the query which will trigger
the findFilm method to show the suggestions*/
onChangeText={text => this.setState({ query: text })}
placeholder="Enter the film title"
renderItem={({ item }) => (
//you can change the view you want to show in suggestion from here
<TouchableOpacity onPress={() => this.setState({ query: item.title })}>
<Text style={styles.itemText}>
{item.title} ({item.release_date})
</Text>
</TouchableOpacity>
)}
/>
Got this from aboutreact.com, comments here explains what you want to pass to specific areas. I suggest trying to pass an array for the data prop.
I'm trying to handle the multi-select with react-native-super-grid , here is my code :
<GridView
itemDimension={80}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer , { backgroundColor:' transparent '}]}>
<TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent() }>
<Text> {item.image}</Text>
</TouchableHighlight>
<Text style={styles.buttonText}> {item.name}</Text>
</View>)}
/>
I tried using this function :
pressEvent(arr){
if(this.state.pressStatus == false){
this.setState({ pressStatus: true})
this.state.arr.push(arr)
this.setState({ color : 'white'})
} else {
this.setState({ pressStatus: false})
this.setState({ color: 'red'})
}
}
but it somehow doesn't work , can someone help me ?
Thank you .
This short example should give you an idea what are you doing wrong. The items itself are not aware of the state. So what I would do, I would create a separate child component for grid item and handle press state locally. Then handle parent, which is holding all the item trough callback about the pressed item.
class MyGridView extends Component {
render() {
return (
<GridView
itemDimension={80}
items={items}
style={styles.gridView}
renderItem={item => (
<GridItem
item={item}
onItemPress={selected => {
// set grid view callback
if (selected) {
//if true add to array
this.addToPressedArray(item);
} else {
//false remove from array
this.removeFromPressedArray(item);
}
}}
/>
)}
/>
);
}
// You don't change the state directly, you mutate it trough set state
addToPressedArray = item => this.setState(prevState => ({ arr: [...prevState.arr, item] }));
removeFromPressedArray = item => {
const arr = this.state.arr.remove(item);
this.setState({ arr });
};
}
And the GridItem
class GridItem extends Component {
// starting local state
state = {
pressStatus: false,
color: 'red'
};
// handle on item press
pressEvent = () => {
this.setState(prevState => ({
pressStatus: !prevState.pressStatus, //negate previous on state value
color: !prevState.pressStatus ? 'white' : 'red' //choose corect collor based on pressedStatus
}));
// call parent callback to notify grid view of item select/deselect
this.props.onItemPress(this.state.pressStatus);
};
render() {
return (
<View style={[styles.itemContainer, { backgroundColor: ' transparent ' }]}>
<TouchableHighlight style={styles.buttonStyle} onPress={() => this.pressEvent()}>
<Text> {item.image}</Text>
</TouchableHighlight>
<Text style={styles.buttonText}> {item.name}</Text>
</View>
);
}
}
I also recommend to read about React.Component lifecycle. Its a good reading and gives you a better understanding how to achieve updates.
Since GridView has been merged into FlatGrid. Therefore, I've implemented the multi-select option in a pretty easy way. First of all I applied TouchableOpacity on top of the view in the renderItems prop of FlatGrid like this.
<TouchableOpacity
onPress={() => this.selectedServices(item.name)}>
...props
</TouchableOpacity>
SelectedServices:
selectedServices = item => {
let services = this.state.selectedServices;
if (services.includes(item) == false) {
services.push(item);
this.setState({ selectedServices: services });
} else {
let itemIndex = services.indexOf(item);
services.splice(itemIndex, 1);
this.setState({ selectedServices: services });
}
};
Using splice, indexOf, and push, you can easily implement multi-selection.
To change the backgroundColor of the currently selected item, you can apply a check on the backgroundColor prop of the view.
renderItem={({ item, index }) => (
<TouchableOpacity
onPress={() => this.selectedServices(item.name)}
>
<View
style={[
styles.itemContainer,
{
backgroundColor: this.state.selectedServices.includes(
item.name
)
? '#0052cc'
: item.code
}
]}
>
<Text style={styles.itemName}>{item.name}</Text>
</View>
</TouchableOpacity>
)}