Passing values dynamically to child component react native - react-native

App.js
render() {
return (
<View style={{ flex: 1, marginTop: 20 }}>
<Button
title="Learn More"
color="#841584"
accessibilityLabel="Learn more about this purple button"
onPress={() => {
(this.state.dadda = '2017-09-07');
}}
/>
<EventCalendar
eventTapped={this._eventTapped.bind(this)}
events={this.state.events}
width={width}
initDate={this.state.dadda}
scrollToFirst={false}
/>
</View>
); }
This is my parent component ,I want to pass initDate to event calendar component,I want to update the date when the button is pressed?

You should not mutate the state by assigning value to the state variable directly but instead use setState to acheive that.
<Button
title="Learn More"
color="#841584"
accessibilityLabel="Learn more about this purple button"
onPress={() => this.setState({dadda: '2017-09-07'})}
/>

The way you are setting dadaa into the state is not correct, use this.setState function instead, have a look at the doc.
Change your onPress handler to
...
< Button
title = "Learn More"
color = "#841584"
accessibilityLabel = "Learn more about this purple button"
onPress = {
() => {
this.setState({
dadda:'2017-09-07'
});
}
}
/>
...
Also, don't declare the function inside render, rather keep it at the class level like
onPressHandler = () => {
this.setState({
dadaa: 'aaaa'
});
}
render() {
return (
...
<
Button
...
onPress = {this.onPressHandler}
...
/>
...
);
}
Hope this will help!

Related

How to change state of react hook inside other component

Senario
I have a dialog, it look something like this, it have hook for showing this dialog, called showDialog , and dialog have a button with Onpress method
export default function DialogTesting(show: boolean) {
const [showDialog, doShow] = useState(show)
return (
<View>
{/* <Button
title="click"
onPress={() => {
setShow(true)
}}
>
<Text>Show dialog</Text>
</Button> */}
<Dialog
visible={showDialog}
title="Record New Progress"
style={DIALOG}
onClose={() => {
doShow(false)
}}
>
And a main sceen , it also have hook to show dialog, called show,
export const MedicalRecord = memo(function MedicalRecord() {
// const onPressViewAll = useCallback(() => {}, [])
const [show, setShow] = useState(false)
function hanndleDialog() {
setShow(!show)
}
return (
<SummaryViewContainer
count={5}
title={"dashboardScreen.medicalRecords.title"}
onPress={() => {
hanndleDialog()
}}
>
<View>
{show && (
<ProgressDialog
show={show}
callback={() => {
hanndleDialog()
}}
/>
)}
<RecordItem />
<RecordItem />
<RecordItem />
</View>
</SummaryViewContainer>
)
})
Problem
When i click the button in main screen, change hook show to true to show dialog, and use this hook state in dialog to set show in dialog to true to show that dialog, and in dialog, when i click button to close dialog, it disappear, but problem is, the state of show in main screen remain true, so i have to press twice to show dialog again
Question
How can i change hook status in main screen, or how can i press close button in dialog, the show hook in main screen return false, i tried to change state of mainscreen in dialog but it won't work
Here is a short video of problem
https://streamable.com/9mm26t
You should maintain just one copy of your state in the parent component itself. Then pass "show" and "setShow" as props to the child component.
Parent Component:
export const MedicalRecord = memo(function MedicalRecord() {
// const onPressViewAll = useCallback(() => {}, [])
const [show, setShow] = useState(false)
function hanndleDialog() {
setShow(!show)
}
return (
<SummaryViewContainer
count={5}
title={"dashboardScreen.medicalRecords.title"}
onPress={() => {
hanndleDialog()
}}
>
<View>
{show && (
<ProgressDialog
show={show}
setShow = {setShow}
/>
)}
<RecordItem />
<RecordItem />
<RecordItem />
</View>
</SummaryViewContainer>
)
})
Dialog Component:
export default function DialogTesting({show, setShow}) {
return (
<View>
{/* <Button
title="click"
onPress={() => {
setShow(true)
}}>
<Text>Show dialog</Text>
</Button> */}
<Dialog
visible={show}
title="Record New Progress"
style={DIALOG}
onClose={() => {
setShow(false)
}}
>
</View>
)
}
It looks like you have 2 versions of local state at each component. You need to keep 1 version of "show" at the top most parent where you care to control this variable and then pass it down as a prop to your child components. Then on your child components you need to expose a callback that the parent will pass down and the child will call to trigger what occurs when the button is clicked in the child component.

FlatList not rendering style dynamically

I'm currently struggling in making my FlatList applying the changes I do to it. What I am wanting right now is that when I click an item in my flatlist, that it highlights in a certain color. I followed an approach done by a guy but I am having the problem that to me is not working the update once I click.
I can see through console that all I am doing performs a modification but I think that I am missing some point with extraData parameter since it is not re-rendering with the backgroundColor that I would like to apply.
The code I have is as following, I know that the style I am applying is correct since if i substitute in the map styles.list per styles.selected, everything gets the background I would like to be applied to the elements I click.
So summarizing, the issue I think I have is that the flatlist is not re-rendering so it doesn't show the modifications I perform on it. Any idea of what I am doing wrong? Any tip?
render() {
const { students, studentsDataSource, loading, userProfile } = this.props.navigation.state.params.store;
this.state.dataSource = studentsDataSource._dataBlob.s1.map(item => {
item.isSelect = false;
item.selectedClass = styles.list;
return item;
})
const itemNumber = this.state.dataSource.filter(item => item.isSelect).length;
return (
<View style={styles.container}>
<Item rounded style={styles.searchBar}>
<Input placeholder='Group Name'/>
</Item>
<FlatList
style={{
flex: 1,
width: "100%",
}}
data={this.state.dataSource}
ItemSeparatorComponent={this.FlatListItemSeparator}
renderItem={ ({ item }) => (
<ListItem avatar style={[styles.list, item.selectedClass]}
onPress={() => this.selectItem(item)}>
<Left>
{!item.voteCount && <Avatar unseen={true} /> }
{!!item.voteCount > 0 && <Avatar />}
</Left>
<Body>
<Text>{item.name}</Text>
<Text note>{item.group}</Text>
</Body>
</ListItem>
)
}
listKey={item => item.key}
extraData={this.state}
/>
</View>
);
}
Here we can find the state and SelectItem functions:
constructor(props) {
super(props)
this.state = {
dataSource : [],
}
}
//FlatListItemSeparator = () => <View style={styles.line} />;
selectItem = data => {
//{console.log("inside SelectItem=", data)}
data.isSelect = !data.isSelect;
data.selectedClass = data.isSelect? styles.selected: styles.list;
const index = this.state.dataSource.findIndex( item => data.key === item.key);
this.state.dataSource[index] = data;
this.setState({
dataSource: this.state.dataSource,
});
console.log("This state has the changes:=",this.state.dataSource)
};
Well the main issue was that I was not using the .setState and instead I was doing assignations which killed the listeners.

I am using react-native-swiper-flatlist , but I cannot figure it out how to use scrollToIndex on button press

I am using react-native-swiper-flatlist , I want to scroll forward to some index by tapping button but no clue how to do it. Although I am very beginner to react native development.
I have searched alot but nothing helps, I get an error of undefined is not an object this2.swiper.scrollToIndex'
render() {
return (
<View style={styles.container}>
<SwiperFlatList
ref={swiper => {
this.swiper = swiper;
}}
data={[
{ key: "a" },
{ key: "b" },
{ key: "c" },
{ key: "d" },
{ key: "e" }
]}
index={0}
renderItem={({ item, index }) => (
<View>
<Image
style={styles.child}
source={require("../../assets/advertisementtwo.png")}
/>
<Image
style={styles.child}
source={require("../../assets/advertisementtwo.png")}
/>
<Image
style={styles.child}
source={require("../../assets/advertisementtwo.png")}
/>
<Image
style={styles.child}
source={require("../../assets/advertisementtwo.png")}
/>
<Button
title={"Next"}
onPress={this.swiper.scrollToIndex(1, true)}
style={{ backgroundColor: "white" }}
/>
</View>
)}
/>
</View>
);
}
Should swipe on button click
Here is the screenshot of the error I am getting
Try adding ref='swiper' as a SwiperFlatList prop,
Example
<SwiperFlatList ref='swiper'/>
this.refs.swiper._scrollToIndex(2)
For those who are using React hook instead of class, you can do sth like that to utilise the scrollToIndex function
//First, make a ref for storing the swiper instance inside your swiper compoent
const swiperRef = useRef<any>({});
//Second, store the reference
<SwiperFlatList
ref={(component) => { swiperRef.current._swiper = component; }}
>
//Later on, you can call the function like this
swiperRef.current._swiper.scrollToIndex({index: 2})

Ternary operator in react-native

I need to show a component only if a variable is true, basically I'm going to create two buttons, one to set variable to false and another to true. I'm trying to use the * ngIf idea of the Angular. I need something like this:
render() {
return (
<View>
<Button
title="Click me"
onPress={ () => { this.loading = true } }
/>
{this.loading ? <Modal /> : null}
</View>
);
}
It seems you are new to React, in react state and handlers are either held in state or passed has props.
you can achieve this having a component state like show , have click handlers which set the State then in render you can check this.state.show and take decision to either show the component or not
setShow = () = >{
this.setstate({show : true});
}
render() {
return (
<View>
<Button
title="Click me"
onPress={this.setShow}
/>
{this.state.show ? <Modal /> : null}
</View>
);
}

React native add active class when push the button

I have a 3 buttons on react native project iOS app. How can I set class active to clicked button and delete this class from others? Like addClass/removeClass that I had used on jquery?
First have your define your style "class".
const styles = StyleSheet.create({
btnSelected: {
...
},
notSelected : {
}
});
Then you can use a state property in your react component.
example :
state = {
btnSelected: 1
}
<Button
style={(this.state.btnSelected== 1)?styles.btnSelected:styles.notSelected}
onPress={() => this.setState({ btnSelected: 1 })} ... />
<Button
style={(this.state.btnSelected== 2)?styles.btnSelected:styles.notSelected} ...
onPress={() => this.setState({ btnSelected: 2 })} .../>
<Button
style={(this.state.btnSelected== 3)?styles.btnSelected:styles.notSelected}
onPress={() => this.setState({ btnSelected: 3 })} ... />
The key concept in React and React Native is, that you don't imperatively set the state of your UI. Instead, you change some state, and then declaratively render the UI based on that.
You could, for example use the local component state (this.state):
class Buttons extends React.Component {
state = {
activeButton: 'first'
}
render() {
return (
<View>
<Button
onPress={() => this.setState({ activeButton: 'first' })}
isActive={this.state.activeButton === 'first'}
/>
<Button
onPress={() => this.setState({ activeButton: 'second' })}
isActive={this.state.activeButton === 'second'}
/>
<Button
onPress={() => this.setState({ activeButton: 'third' })}
isActive={this.state.activeButton === 'third'}
/>
</View>
)
}
}
The onPress event handler sets local component state with setState, which causes the component to immediately re-render. The isActive property is then set on all the buttons based on the expression that compares this.state.activeButton with some value.