I want to use a value, from the file Step3.js in Step4.js, the value can change after user input in Step3. But how can I use this value in Step4?
I have tried some things, but I guess I miss the point here, so hopefully somebody can help me out with this.
This is my code:
App.js:
import React, { Component } from 'react'
import { AppRegistry, StyleSheet, View, Text } from 'react-native'
import { ViewPager } from 'rn-viewpager'
import StepIndicator from 'react-native-step-indicator'
import Step1 from "./Step1";
import Step2 from "./Step2";
import Step3 from "./Step3";
import Step4 from "./Step4";
const PAGES = [{id: 1, page: <Step1/>},{id: 2, page: <Step2/>}, {id: 3, page: <Step3/>}, {id: 4, page: <Step4/>}];
const firstIndicatorStyles = {
stepIndicatorSize: 30,
currentStepIndicatorSize: 40,
separatorStrokeWidth: 5,
currentStepStrokeWidth: 3,
separatorFinishedColor: '#4aae4f',
separatorUnFinishedColor: '#a4d4a5',
stepIndicatorFinishedColor: '#4aae4f',
stepIndicatorUnFinishedColor: '#a4d4a5',
stepIndicatorCurrentColor: '#ffffff',
stepIndicatorLabelFontSize: 15,
currentStepIndicatorLabelFontSize: 15,
stepIndicatorLabelCurrentColor: '#000000',
stepIndicatorLabelFinishedColor: '#ffffff',
stepIndicatorLabelUnFinishedColor: 'rgba(255,255,255,0.5)',
labelColor: '#666666',
labelSize: 12,
currentStepLabelColor: '#4aae4f'
};
export default class App extends Component {
constructor (props) {
super(props);
this.state = {
currentPosition: 0,
stepCount: 4,
}
}
componentWillReceiveProps (nextProps, nextState) {
if (nextState.currentPosition != this.state.currentPosition) {
if (this.viewPager) {
this.viewPager.setPage(nextState.currentPosition)
}
}
}
render () {
return (
<View style={styles.container}>
<ViewPager
style={{ flexGrow: 1 }}
ref={viewPager => {
this.viewPager = viewPager
}}
onPageSelected={page => {
this.setState({ currentPosition: page.position })
}}
>
{PAGES.map(page => this.renderViewPagerPage(page))}
</ViewPager>
<View style={styles.stepIndicator}>
<StepIndicator
customStyles={firstIndicatorStyles}
currentPosition={this.state.currentPosition}
stepCount={this.state.stepCount}
labels={['Kleur', 'Vorm', 'Moeite', 'Overzicht']}
/>
</View>
</View>
)
}
renderViewPagerPage = (data) => {
console.log(data);
console.log(this.state.currentPosition);
return (
<View key={data.id}>
{data.page}
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#ffffff'
},
stepIndicator: {
marginVertical: 20
},
});
Step3.js:
export function getSelected3() {
return this.state.selected;
}
class Step3 extends Component {
constructor(props){
super(props);
this.state = {
happy: {
"id" : "1",
"name" : "happy",
"src" : require('../../assets/images/makkelijk.png')
},
normal: {
"id" : "2",
"name" : "normal",
"src" : require('../../assets/images/gemiddeld.png'),
},
sad: {
"id" : "3",
"name" : "sad",
"src" : require('../../assets/images/moeilijk.png'),
},
selected: {
"id" : "4",
"name" : "",
"src" : require('../../assets/images/moeilijk.png'),
},
};
}
onPress = (item) => {
this.state.selected.name = item.name;
this.state.selected.src = item.src;
alert(this.state.selected.name);
};
render() {
return (
<View style={styles.container}>
<View style={[styles.box]}>
<TouchableHighlight onPress={() => this.onPress(this.state.happy)}>
<Image
style={styles.image}
source={this.state.happy.src}
/>
</TouchableHighlight>
</View>
<View style={[styles.box]}>
<TouchableHighlight onPress={() => this.onPress(this.state.normal)}>
<Image
style={styles.image}
source={this.state.normal.src}
/>
</TouchableHighlight>
</View>
<View style={[styles.box]}>
<TouchableHighlight onPress={() => this.onPress(this.state.sad)}>
<Image
style={styles.image}
source={this.state.sad.src}
/>
</TouchableHighlight>
</View>
</View>
)
}
}
So I want to use the date from the state in Step3 selected into Step4.js, How can I Do this?
Step4.js:
class Step4 extends Component {
constructor(props) {
super(props);
this.state = {
value3: {
"id": "3",
"name" : "",
"src" : "",
},
};
}
render() {
let test = getSelected3();
this.state.value3.src = value3.src;
return (
<View style={styles.container}>
<View style={[styles.box]}>
<TouchableHighlight>
<Image
style={styles.image}
source={this.state.value3.src}
/>
</TouchableHighlight>
</View>
<View style={[styles.box]}>
<TouchableHighlight>
<Image
style={styles.image}
source={this.state.value3.src}
/>
</TouchableHighlight>
</View>
<View style={[styles.box]}>
<TouchableHighlight>
<Image
style={styles.image}
source={this.state.value3.src}
/>
</TouchableHighlight>
</View>
</View>
)
}
Suggest you to make Step3 and Step4 components stateless which will receive only props and create a component Stepper which will render both Step3 and Step4. Stepper component will do all the state manipulations.
class Stepper extents Component {
render() {
const { state1, state2, state3, state4, onPress } = this.state;
return [
<Step3 state1={state1} state3={state3} onPress={onPress} />,
<Step4 state2={state2} state4={state4} />
];
}
}
And Step3 would look like this:
const Step3 = ({ state1, state2, onPress }) => {
return (<TouchableHighlight onPress={onPress}></TouchableHighlight);
};
Hope you get the idea.
Copy pasting my answer from a similar question
I usually create a global.js containing:
module.exports = {
step3State: null,
};
And get the value of the state on the screen
render() {
GLOBAL.step3State = this;
//enter code here
}
Now you can use it anywhere like so:
GLOBAL.step3State.setState({
var: value
});
or
Global.step3State.state.value
Related
Can anyone tell me how to solve these things?
1.if the list is pressed, I'd like to change the background color of the list
beige(#FFF5E7) to white(#FBFBFB)
2.Also, I'd like to change the read value of the Object fales to true with useState
Problem is that if I pressed the list, whole background color of the list will be changed.
index.tsx
import React, { useState } from 'react';
import { Text, View, TouchableOpacity, FlatList } from 'react-native';
import { useNavigation } from '#react-navigation/native';
import { DETAIL } from '../../sample';
import { Object } from './sample';
export default function sample() {
const [state, setState] = useState(Object);
const navigation = useNavigation();
let Element;
const renderItem = ({ item }) => {
const readState = () => {
navigation.navigate(NOTICE_DETAIL);
const readValue = [...state];
let value = { ...readValue[0] };
value.read = true;
readValue[0] = value;
setState(readValue);
};
if (state[0].read) {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FBFBFB' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
} else {
Element = (
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: '#FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
);
}
return Element;
};
}
return (
<View style={{ flex: 1 }}>
<FlatList
extraData={Object}
data={Object}
renderItem={renderItem}
/>
</View>
);
}
Object.ts
export const Object = [
{
id: 1,
text: 'testtesttest',
content: 'testtesttest'
read: false
},
{
id: 2,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
id: 3,
text: 'testtesttest',
content: 'testtesttest'
read: false
}
]
We can add inline styles into the component style props along with static styles,
For Example:
<TouchableOpacity onPress={readState}>
<View style={[styles.row, { backgroundColor: item.read ? '#FBFBFB' : 'FFF5E7' }]}>
<View style={styles.container}>
<View style={styles.end}>
<Text style={styles.text}>{item.text}</Text>
<Text style={styles.time}>{item.time}</Text>
</View>
<Text style={styles.content}>{item.content}</Text>
</View>
</View>
</TouchableOpacity>
Problem in your readState function and if (state[0].read) {. You always change item with index 0 and then check state[0].read for all elements of your array.
When I tried alert("Hi") in renderMoreView function, it actually works, but to display the View is the problem I am facing
export default class Home extends Component {
state = {
moreButton: false,
};
renderMoreView = () => {
return (
<View style={{flex: 1, height: 50, width: 50}}>
<Text>Hi</Text>
</View>
);
};
render () {
return (
<View>
.....
<TouchableOpacity
underlayColor="transparent"
onPress={() => this.setState ({moreButton: true})}
>
<Feather name="more-vertical" size={25} />
</TouchableOpacity>
...
{this.state.moreButton ? this.renderMoreView () : null}
</View>
);
}
}
This is what I am trying to do]
If I understand your question right, you could use Modal component. https://facebook.github.io/react-native/docs/modal
This can be done using modal. But if you want to do it more simply, install and use the module. react-native-awesome-alerts
$ npm i react-native-awesome-alerts --save
Example
import React from 'react';
import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
import AwesomeAlert from 'react-native-awesome-alerts';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { showAlert: false };
};
showAlert = () => {
this.setState({
showAlert: true
});
};
hideAlert = () => {
this.setState({
showAlert: false
});
};
render() {
const {showAlert} = this.state;
return (
<View style={styles.container}>
<Text>I'm AwesomeAlert</Text>
<TouchableOpacity onPress={() => {
this.showAlert();
}}>
<View style={styles.button}>
<Text style={styles.text}>Try me!</Text>
</View>
</TouchableOpacity>
<AwesomeAlert
show={showAlert}
showProgress={false}
title="AwesomeAlert"
message="I have a message for you!"
closeOnTouchOutside={true}
closeOnHardwareBackPress={false}
showCancelButton={true}
showConfirmButton={true}
cancelText="No, cancel"
confirmText="Yes, delete it"
confirmButtonColor="#DD6B55"
onCancelPressed={() => {
this.hideAlert();
}}
onConfirmPressed={() => {
this.hideAlert();
}}
/>
</View>
);
};
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fff',
},
button: {
margin: 10,
paddingHorizontal: 10,
paddingVertical: 7,
borderRadius: 5,
backgroundColor: "#AEDEF4",
},
text: {
color: '#fff',
fontSize: 15
}
});
I need your help I'm using firebase for my app. I'm trying to get the users ID not the logged users no all users I have. I want to show their (uid) simply like in an alert for each user. Also, I'm showing them in a flatlist and when I set item.uid in an alert it shows (undefined). But, all the other data of the user is shown correctly. This what I did until now:
**
users.js
**
export default class usersList extends React.Component{
state = {
loading: false,
uid: '',
users: [],
items: []
};
componentDidMount() {
let itemsRef = f.database().ref('users').once('value').then(snapshot => {
var data = snapshot.val();
var items = Object.values(data);
this.setState({items});
console.log(snapshot.val())
});
}
renderItem({item}) {
return (
<View key={index} style={{width: '100%', overflow:'hidden', marginBottom: 5, justifyContent:'space-between', borderBottomWidth:1, borderColor: 'grey'}}>
<View>
<View style={{padding:5, width:'100%', flexDirection: 'row', justifyContent: 'space-between'}}>
<Text>{item.email}</Text>
</View>
</View>
</View>
)
}
render() {
return (
<View style={styles.container}>
<ScrollView>
{
this.state.items.length > 0
? <ItemComponent items={this.state.items} navigation={this.props.navigation} />
: <Text>No stores</Text>
}
</ScrollView>
</View>
);
}
}
//ItemComponent.js
export default class ItemComponent extends Component {
static propTypes = {
items: PropTypes.array.isRequired
};
render() {
return (
<View style={styles.itemsList}>
{this.props.items.map((item, index) => {
return (
<View key={index}>
<TouchableOpacity
onPress={ () => alert(item.uid)}>
<Text style={styles.itemtext}>{item.email}</Text>
</TouchableOpacity>
</View>
)
})}
</View>
);
}
}
firebase.database().ref('user').on('value', (datasnapshot) => {
this.setState({
_id: datasnapshot.key
});`
This solution worked for me
<Text style={styles.yourStyleHere}>UID: {auth.currentUser?.uid} </Text>
My ReactNative FlatList is not rendering with this simple implementation.
<FlatList style={{flex:1, backgroundColor:'red'}}
data = {this.state.users}
keyExtractor={item => item.key.toString()}
renderItem={({item}) => {
return (
<ChatUserCard key={item.uid} username={item.username} />
)
}}
/>
ChatUserCard
<View style={styles.cardStyle}>
<Text style={styles.itemStyle}>{this.props.username}</Text>
<Button style={styles.buttonStyle}
title='Chat'
onPress={this.startChat} />
</View>
Try add comments to the view below the flatlist and remove flex 1 from the styles on the flatlist. Try that to check if it is related with the styles
I'm thinking what's going on is that you've not wrapped your FlatList in a View that has flex: 1 set. Also, you can probably use your uid as your key, rather than setting a key in your object data
Demo
https://snack.expo.io/#anonymoussb/so53688423
import * as React from 'react';
import { Text, View, StyleSheet, Button, FlatList } from 'react-native';
class ChatUserCard extends React.Component {
render() {
return (
<View style={styles.cardStyle}>
<Text style={styles.itemStyle}>{this.props.username}</Text>
<Button style={styles.buttonStyle}
title='Chat'
onPress={this.startChat} />
</View>
)
}
}
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [
{ key: 123, uid: 123, username: 'taco' },
{ key: 456, uid: 456, username: 'cat' }
]
}
}
render() {
return (
<View style={styles.container}>
<FlatList style={{flex:1, backgroundColor:'red'}}
data = {this.state.users}
keyExtractor={item => item.key.toString()}
renderItem={({item}) => {
return (
<ChatUserCard key={item.uid} username={item.username} />
)
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
});
I am making a music app using react-native-track-player. I made 3 components called Clusters, Songlist and Play.
How screen works
Clusters component -> Songlist component -> Play component. Problem for me is that I don't know how to pass the index of the song selected to the SongList component from Clusters component which will also allow me to pass it to my Play component. I am not sure how to do it.
I created data. First screen shows title and mood(Songlist component). Second screen (Songlist shows the playlist depending on the title that I clicked.
This is my where I get my data in another file
const ClusterData = [
{
title: "Cluster1",
data: [
{ name: "passionate" },
{ name: "rousing" },
{ name: "confident" },
{ name: "boisterous" },
{ name: "rowdy" }
],
songlist: [
{
id: "2222",
url: "http://tegos.kz/new/mp3_full/Post_Malone_-_Better_Now.mp3",
title: "Better Now",
artist: "Post Malone"
},
{
id: "2",
url:
"http://tegos.kz/new/mp3_full/5_Seconds_Of_Summer_-_Youngblood.mp3",
title: "YoungBlood",
artist: "5SOS"
}
]
},
{
title: "Cluster2",
data: [
{ name: "rollicking" },
{ name: "cheerful" },
{ name: "fun" },
{ name: "sweet" },
{ name: "amiable" },
{ name: "natured" }
],
songlist: [
{
id: "1111",
url:
"http://tegos.kz/new/mp3_full/Yellow_Claw_and_San_Holo_-_Summertime.mp3",
title: "Summertime",
artist: "Yellow Claw"
},
{
id: "1",
url:
"http://tegos.kz/new/mp3_full/Luis_Fonsi_feat._Daddy_Yankee_-_Despacito.mp3",
title: "Despacito",
artist: "Luis Fonsi"
}
]
}
];
This is my Clusters screen (first screen)
export default class Clusters extends Component {
render() {
return (
<View style={styles.container}>
<SectionList
renderItem={({ item, index }) => {
return (
<SectionListItem item={item} index={index}>
{" "}
</SectionListItem>
);
}}
renderSectionHeader={({ section }) => {
return <SectionHeader section={section} />;
}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}
/>
</View>
);
}
}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>{this.props.section.title}</Text>
<TouchableOpacity
onPress={() => Actions.SongList({ section: this.props.section })}
>
<Text style={styles.Play}> Play</Text>
</TouchableOpacity>
</View>
);
}
}
class SectionListItem extends Component {
render() {
return (
<View>
<Text style={styles.moodname}>{this.props.item.name}</Text>
</View>
);
}
}
This is my SongList screen (second screen)
export default class App extends Component {
render() {
return (
<View>
<FlatList
data={this.props.section.songlist}
renderItem={({ item, index, rowId }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
render() {
return (
<View>
<TouchableOpacity
onPress={() =>
Actions.Play({
songlist: this.props.item.songlist,
item: this.props.item
})
}
>
<Text style={styles.itemTitle}>{this.props.item.songtitle}</Text>
<Text style={styles.itemArtist}>{this.props.item.artist}</Text>
</TouchableOpacity>
</View>
);
}
}
This is my Play screen
import TrackPlayer from "react-native-track-player";
export default class Play extends Component {
componentDidMount() {
TrackPlayer.setupPlayer().then(async () => {
// Adds a track to the queue
await TrackPlayer.add(this.props.item.songlist[index]);
// Starts playing it
TrackPlayer.play();
});
}
onPressPlay = () => {
TrackPlayer.play();
};
onPressPause = () => {
TrackPlayer.pause();
};
render() {
return (
<View style={styles.container}>
<View style={{ flexDirection: "column" }}>
<TouchableOpacity style={styles.play} onPress={this.onPressPlay}>
<Text
style={{
fontWeight: "bold",
textAlign: "center",
color: "white"
}}
>
Play
</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.pause} onPress={this.onPressPause}>
<Text
style={{
fontWeight: "bold",
textAlign: "center",
color: "white"
}}
>
Pause
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
export default class App extends Component {
setSong(var selectedSong){
// do something with the selectedsong, maybe in the state
this.setState({currentSong: selectedSong});
}
render() {
return (
<View>
<FlatList
data={this.props.section.songlist}
renderItem={({ item, index, rowId }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
You need something like this
export default class App extends Component {
this.state = {
index:0
}
setSong(var selectedSong){
var index = this.props.songlist.index(selectedSong);
this.setState({index: index});
}
render() {
return (
<View>
<FlatList
data={this.props.section.songlist}
renderItem={({ item, index, rowId }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
this.state = {
index:0
}
setSong(var selectedSong){
var index = this.props.songlist.index(selectedSong);
this.setState({index: index});
}
render() {
return (
<View>
<TouchableOpacity
onPress={() =>
Actions.Play({
songlist: this.props.item.songlist,
item: this.props.item,
index: this.state.index,
setSong: () => this.setSong
})
}
>
<Text style={styles.itemTitle}>{this.props.item.songtitle}</Text>
<Text style={styles.itemArtist}>{this.props.item.artist}</Text>
</TouchableOpacity>
</View>
);
}
}
just try passing a function as a prop that you can call in the child
function setSong(var selectedSong){
// do something with the selectedsong, maybe in the state
this.setState({currentSong: selectedSong});
}
and then pass this function
<TouchableOpacity
onPress={() =>
Actions.Play({
songlist: this.props.item.songlist,
item: this.props.item,
setSong: () => this.setSong
})
}
>