creating component in onPress event - react-native

I'm trying to build an android app using functional react-native and expo.
I want to know to create new components inside other components when events are triggered.
What I'm trying to do is the following
The code I wrote is below:
<View>
<TouchableOpacity style = {styles.container} onPress = {() => {return (
<TouchabeOpacity>
<Text> Hello World </Text>
</TouchabeOpacity> ) }}
</ToucchabeOpacity>
</View>
I want when pressing the first touchableopacity another one would be created and displayed.
Any solutions ?

You need to do something like:
import {NewComponent} from './components/NewComponent';
....
const[displayNewComponent, setDisplayNewComponent] = useState(false)
...
<View>
<TouchableOpacity style = {styles.container} onPress={() => setDisplayNewComponent(true)}
{ displayNewComponent && <NewComponent /> }
</ToucchabeOpacity>
</View>
export const NewComponent = () => {
return (
<TouchabeOpacity>
<Text> Hello World </Text>
</TouchabeOpacity>
)

Related

Change only one icon in a list of objects - React Native

I want to be able to change the icon in a list of todos (see picture) from an exclamation mark, to a checkmark. That should happen if the user puts the finger on the icon, or the developer clicks with the mouse in the emulator.
Through the code below, I manage to change it, but the new icon only appears if I close the modal containing the list, and reopen it. So the modal does not re-render, neither partly nor in whole.
How can I make the changes appear live, immediately after I click the exclamation icon? I suspect it has to do with state, but it doesn't seem possible to create a React hook inside the map function. If I let onPress call a function, then the state is only known within that external function, and I don't know how to export it.
export const TeacherMessages = (props) => {
return (
<View
style={[
styles.borderBox,
props.todos.length > 0 || props.notes.length > 0
? styles.whiteBox
: null,
]}
>
{
props.todos.map((todo) => (
<View key={todo.id} style={styles.listNotes}>
<AntDesign
style={styles.listIcon}
onPress={() => todo.isChecked = true}
name={todo.isChecked ? "checksquare" : "exclamationcircle"}
color={todo.isChecked ? "green" : "red"}
size={18}
/>
<Text style={styles.listText}> {todo.description}</Text>
</View>
))
}
);
I think you need to store the todos array in a react hook so that way the changes you do to it becomes live instantly, You can have this changeTodo function in the parent component and pass it as props to call it from the child component with the index needed. I think this might help:
export const TeacherMessages = (props) => {
const [todosArr, setTodosArr] = React.useState(props.todos)
const checkTodo = (todoIndex) =>{
let arr = [...todosArr]
arr[todoIndex].isChecked= true
setTodosArr(arr)
}
return (
<View
style={[
styles.borderBox,
todosArr.length > 0 || props.notes.length > 0
? styles.whiteBox
: null,
]}
>
{
todosArr.map((todo, index) => (
<View key={todo.id} style={styles.listNotes}>
<AntDesign
style={styles.listIcon}
onPress={() => checkTodo(index)}
name={todo.isChecked ? "checksquare" : "exclamationcircle"}
color={todo.isChecked ? "green" : "red"}
size={18}
/>
<Text style={styles.listText}> {todo.description}</Text>
</View>
))
}
);

useState getting confused when using multiple components

The action taken to update the state in a functional component is incorrectly updating the state of the final component loaded.
I have simplified what I'm doing to very simple code. I'm wondering if I'm missing something in why this does not work
This is parent component that loops to create subcomponents.
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} />
)) : null}
This is the ScoringDay component. I'm simply using a button press to update the text in state and have it displayed.
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
[test, setTest] = useState('starting text');
return(
<View>
<Text>
{test}
</Text>
<Text onPress={() =>setTest('Clicked here')}>Update value</Text>
</View>
)
In my example, 3 "ScoringDay" components are shown on the screen. However, no matter which text "Update value" I click, it always updates the text on the last component.
Why isn't the action being applied to the correct component?? I am using an index on the key...but not sure what else needs to be changed here?
Run the status change from parent to child.
[testtext, setTestText] = useState('starting text');
...
{scoreDays.length >0 ? scoreDays.map((el,idx) =>(
<ScoringDay key={idx} date ={el.day} score={el.score}
channels={el.channels} testtext={testtext} setTestText={setTestText} />
)) : null}
Used
const ScoringDay = props => {
[expanded, setExpanded] = useState(false);
const { testtext, setTestText} = props
return(
<View>
<Text>
{testtext}
</Text>
<Text onPress={() =>setTestText('Clicked here')}>Update value</Text>
</View>
)

fetching data from api in react-native snap carousel but not working properly

I am using your react-native Snap carousel, It works great, But I am trying to get data from API, It worked but It shows me total data in one card. How can i show it separately?
Here is the code:
List.js
mainExample () {
const { slider1ActiveSlide } = this.state;
return (
<View>
<Carousel
data={data}
/>
<Pagination
dotsLength={length}
/>
</View>
);
}
SliderEntry.js
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => { alert(`You've clicked`); }}
>
<View>
{Title}
<Text
>
{available}
</Text>
</View>
</TouchableOpacity>
);
It's showing all fetched data in one card. Anyone Please help me!
This has absolutely nothing to do with the plugin itself.
Since you're already passing responseMsg._embedded.items to the Carousel, you should just leverage the prop data of your SliderEntry component instead of referencing it again and mapping it.
const { name, available } = data;
return (
<TouchableOpacity>
<Text>{ name }</Text>
<Text>{ available }</Text>
</<TouchableOpacity>
);

React native onPress with TouchableWithoutFeedback is not working

I am developing a simple React Native application for learning purpose. I am just taking my initial step to get into the React Native world. But in this very early stage, I am having problems. I cannot get a simple touch event working. I am implementing touch event using TouchableWithoutFeedback. This is my code.
class AlbumList extends React.Component {
constructor(props)
{
super(props)
this.state = {
displayList : true
}
}
componentWillMount() {
this.props.fetchAlbums();
}
albumPressed(album)
{
console.log("Touch event triggered")
}
renderAlbumItem = ({item: album}) => {
return (
<TouchableWithoutFeedback onPress={this.albumPressed.bind(this)}>
<Card>
<CardSection>
<Text>{album.artist}</Text>
</CardSection>
<CardSection>
<Text>{album.title}</Text>
</CardSection>
</Card>
</TouchableWithoutFeedback>
)
}
render() {
let list;
if (this.state.displayList) {
list = <FlatList
data={this.props.albums}
renderItem={this.renderAlbumItem}
keyExtractor={(album) => album.title}
/>
}
return (
list
)
}
}
const mapStateToProps = state => {
return state.albumList;
}
const mapDispatchToProps = (dispatch, ownProps) => {
return bindActionCreators({
fetchAlbums : AlbumListActions.fetchAlbums
}, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(AlbumList);
As you can see, I am implementing touch event on the list item. But it is not triggering at all when I click on the card on Simulator. Why? How can I fix it?
You should wrap your content in component like this:
<TouchableWithoutFeedback>
<View>
<Your components...>
</View>
</TouchableWithoutFeedback>
TouchableWithoutFeedback always needs to have child View component. So a component that composes a View isn't enough.
So instead of
<TouchableWithoutFeedback onPressIn={...} onPressOut={...} onPress={...}>
<MyCustomComponent />
</TouchableWithoutFeedback>
use:
<TouchableWithoutFeedback onPressIn={...} onPressOut={...} onPress={...}>
<View>
<MyCustomComponent />
</View>
</TouchableWithoutFeedback>
See the github issue for more info
Can be used with <TouchableOpacity activeOpacity={1.0}> </TouchableOpacity>
For those who struggle with this issue in react-native 0.64, and wrapping it in just a View doesn't work, try this:
<TouchableWithoutFeedback onPress={onPress}>
<View pointerEvents="none">
<Text>Text</Text>
</View>
</TouchableWithoutFeedback>
In my case i accidentally imported TouchableWithoutFeedback from react-native-web instead of react-native. After importing from react-native everything worked as expected.
In more recent React Native versions, just use Pressable instead:
https://reactnative.dev/docs/pressable
In my case, there was a shadow underneath, which caused instability. What I did to solve it was quite simple: zIndex: 65000
<View style={{ zIndex: 65000 }}>
<TouchableWithoutFeedback onPressIn={() => {}>
<View>
</View>
</TouchableWithoutFeedback>
</View>

How to identify which view is clicked programmatically

I am developing an android application on react native. Which has several buttons and I want to perform different actions on click of each button.
I am quite familiar with android sdk, in android sdk android:id attribute is present to identify components. But the problem in react native is how to identify which button is clicked by user.
<View style = { styles.button_container } >
<Text
onPress={() => } >Component
</Text>
<Text
onPress={() => } >About
</Text>
</View>
you can send a parameter with the button clicked, something like this:
function MenuComponent(props) {
return (
<View style = { styles.button_container } >
<Text
onPress={() => props.onClick('component')} >Component
</Text>
<Text
onPress={() => props.onClick('about')} >About
</Text>
</View>
)
}
Assuming you are sending an onClick prop from the parent. The the parent will know which of the children elements was clicked.
class ParentComponent extends Component {
onClickMenu = (button) => {
console.log(button);
}
render() {
return (
<View>
<MenuComponent onClick={this.onClickMenu} />
</View>
);
}
}
The onClickMenu will get the button param with the clicked button on the child component, from there you can decide what to do for each case.