Unable to call Method from another class in React Native - react-native

I have the following Snack setup (please use Android version):
https://snack.expo.io/#sj458147/stackoverflow-unable-to-call-method
When clicking Go to step 2 - I get undefined is not an object, the View should scroll by calling the method - moveToPage
If a user was to swipe the Modal View, it would move to next the next View. How can I stop this interaction (the view should only scroll when the user clicks a button and not by swiping).
Expo gives the message this.refs is deprecated, how would I update this code?

you need to use React.createRef() in your constructor. And use this reference in your component. In go() function, to achieve moveToPage(2) you need to use current of your reference like in the below;
class ShowModal2 extends Component {
constructor(props){
super(props);
this.MyScrollView = React.createRef();
}
go = () => {
this.MyScrollView.current.moveToPage(2);
};
render() {
return (
<Modal
style={styles.modal}
isVisible={true}
onBackdropPress={this.hideModal}>
<MyScrollView ref={this.MyScrollView}>
......
and apply same approach to other class
class MyScrollView extends Component {
constructor() {
super();
this.state = { page: '' }
this.scrollView = React.createRef();
}
moveToPage(page) {
this.scrollView.current.scrollTo({ x: ((page - 1) * device_width), y: 0,
animated: true });
alert(page);
}
render() {
return (
<View style={styles.container}>
<ScrollView ref={this.scrollView} showsHorizontalScrollIndicator={false} horizontal={true} pagingEnabled={true}>
......
and check from link please-> https://snack.expo.io/#sdkcy/stackoverflow-unable-to-call-method

Related

Binding on finish callback after Animated.Value has started animating?

I'm in the midst of learning React Native's Animated library, but have stumbled across a problem for which I'm sure there must be a solution, but can't seem to find it.
Context:
I have a component which creates a new Animated.Value and starts animating it. I then want to pass that single value to sub components so they can all animate in their own away against this canonical value. But I also want some of these sub components to handle the on finished event.
Currently:
The only way the docs explain handling the animation on finished event is by passing a callback function to .start(). But the parent component which starts the animation doesn't know how the multiple sub components intend to handle it.
Question:
Is there anyway to bind this callback after the animation has started? Something like this.props.animatingValue.addOnFinished(...) would be nice :)
Please let me know if I'm misunderstanding something fundamental. Is it a bad idea to pass Animated.Value instances as props? If so, what's a better way to approach this problem?
Thanks!
EDIT (Request for code example):
I'm just making this up as I go, so please forgive any syntax errors, but this should demonstrate what I'm trying to do:
class Parent extends React.Component {
componentDidMount() {
this.setState({
animatedValue: new Animated.Value(0)
}, () => {
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 1000
}).start()
})
}
render() {
return this.state.animatedValue ? (
<View>
<ChildOne animatedValue={this.state.animatedValue} />
<ChildTwo animatedValue={this.state.animatedValue} />
<ChildThree animatedValue={this.state.animatedValue} />
</View>
) : null
}
}
class ChildOne extends React.Component {
componentDidMount() {
// What I'd like to do...
this.props.animatedValue.onFinished(() => { /* ... something ... */ }
}
render() { /* interpolate some style against the animation, not important */ }
}
// same for ChildTwo and ChildThree ...
Something like this would work. Use this approach in all your children.
class Child extends React.Component {
componentDidMount() {
this.props.addAnimationEndedListener(this.onAnimationEnded);
}
onAnimationEnded = (finished)=>{
/*The animation has Ended. Do what you want in the child here*/
};
}
And then in parent,
class Parent extends React.Component {
componentDidMount() {
this.setState({
animatedValue: new Animated.Value(0)
}, () => {
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 1000
}).start(this.onAnimationEnded)
});
this.animationListeners = [];
}
addAnimationEndedListener = (listener)=>{
this.animationListeners.push(listener);
}
onAnimationEnded = ({finished})=>{
this.animationListeners.forEach(notifyListener=>{
notifyListener(finished);
});
}
render() {
return this.state.animatedValue ? (
<View>
<ChildOne animatedValue={this.state.animatedValue} addAnimationEndedListener={this.addAnimationEndedListener} />
<ChildTwo animatedValue={this.state.animatedValue} addAnimationEndedListener={this.addAnimationEndedListener} />
<ChildThree animatedValue={this.state.animatedValue} addAnimationEndedListener={this.addAnimationEndedListener} />
</View>
) : null
}
}

I am trying to open modal from the child component

I have tried many ways but non of these worked. I am trying from 5 days.
I used redux,props,then ref . Non of these helped.
I need the modal to be visible when I call it from another class.
// this is the parent class
export default class Search1 extends React.Component {
constructor(props) {
super(props);
this.setModalVisible1 = this.setModalVisible1.bind(this);
this.state = {
modalVisible1: false,
};
this.closeModal = this.closeModal.bind(this);
}
setModalVisible1(visible) {
this.setState({ modalVisible1: visible });
// this.setModalVisible2(visible);
}
closeModal() {
console.log("modalvi1 value is in closemodal ", this.state.modalVisible1);
this.setState({ modalVisible1: false });
}
render() {
return (
{/* it renders the screen again when I call the */}
<Modal
closeModal={() => this.closeModal}
animationType="slide"
transparent={true}
visible={this.state.modalVisible1}
</Modal>
<NavStack />
);
}
}
// this is the child class
class HomeScreen extends React.Component {
render() {
<TouchableOpacity
style={styles.firstStyle}
onPress={() => {
this.props.closeModal();
);
}}
>
return (
}
The modal should be visible when called from outer child class. It needs to be close when called from the parent class.
I tried using redux. that does not worked. Then I used props. Then I used the ref. None of these helped. Just get tired of this. Help me out of this.
Pass the function to modal
closeModal() {
this.setState({ modalVisible1: false });;
}
<Modal
closeModal={this.closeModal}
animationType="slide"
transparent={true}
visible={this.state.modalVisible1} />
and run it on child component as this.props.closeModal()

How to add value to already existing state in react native?

I have a state property called projectname
this.state={
projectname: ""
}
I need to change the state value (for example from "Project" to "Project-01" ) when a button is clicked.
Here state projectname changes dynamically. I want to know to how to add -01 with project name
You need to use this.setState() to change your component's state.
The common way to do this by using the onPress handler of the Button component:
create a class method that uses this.setState
bind such method in the class constructor
pass the method to the onPress prop of a Button
Here is an example
import React from "react";
import { View, Button } from "react-native";
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
projectname: "Project", // Inital value in your example
};
// Binding the method that will handle the click.
this.onClickHandler = this.onClickHandler.bind(this);
}
// The actual method that will alter the state.
onClickHandler() {
this.setState({
projectname: "Project-01",
});
}
render() {
return() (
<View>
{/* A button with the method passed to onPress. */}
<Button title="Click me" onPress={this.onClickHandler} />
</View>
);
}
}
Now, if you explicitly want to add "-01" to the projectname value, you need to reference the current value of projectname when altering the state:
onClickHandler() {
this.setState({
projectname: this.state.projectname + "-01"
});
}
But you have to be careful because multiple clicks will add multiple times "-01" (for example, 4 clicks will result in "Project-01-01-01-01").
I'm not sure I got your point correctly or not but I think you are looking for something like this
constructor(props) {
super(props);
this.state = {
projectname:"projectname"
};
this.updateState= this.aba.bind(this)
}
updateState () {
this.setState({
projectname : this.state.projectname.concat("-01")
})
}
You can use setState method to change the state like this :
this.setState({
projectname : "new Project name"
})

react-native window.setInterval, trying to display an incrimenting number

I want to display a number that increases once every second, rather than using some kind of time function I am using window.setInterval because eventually I will replace this with some more complicated code that instead of just displaying the number calls some function and displays the result. Here is the code I have right now:
export default class Test extends Component {
constructor(props){
super(props)
this.state = {counter:0}
}
render(){
newCounter = this.state.counter+1 // I am going to replace this
// with something like:
// newCounter = someFunc()
func = this.setState
window.setInterval(function(){
func({counter:newCounter})
},1000);
return(
<View>
<Text>{this.state.counter}</Text>
</View>
)
}
}
It gives me this error: undefined is not an object (evaluating 'this.updater')
how can I do this correctly? Thanks
Try this:
export default class Test extends Component {
constructor(props){
super(props)
this.state = {counter:0}
}
componentDidMount(){
setInterval(() => {
this.setState( prevState => ({counter: prevState.counter + 1}));
},1000);
}
render(){
return(
<View>
<Text>{this.state.counter}</Text>
</View>
)
}
}
Basically, you want to use the function arrow with set Interval, to not lose the context of the this keyword, and try to use set State outside of the render method.
Here is a demo as well: https://snack.expo.io/HkikISZMm

How do I alternate two Images in a react native component

I'm trying to animate an icon in React native by simply switching the image every 500ms. My code looks like this:
export default class FlashingIcon extends Component {
constructor(props) {
super(props);
this.state = {
on: true,
};
setInterval(() => {
this.setState(previousState => {
return {
on: !previousState.on,
};
});
}, 500);
}
render() {
let sprite = this.state.on
? require('../onIcon.png')
: require('../offIcon.png');
return (
<Image
source={sprite}
style={{width:16, height:20}}
/>
);
}
}
The code is basically copy-and-pasted from:
https://facebook.github.io/react-native/docs/state.html and
https://facebook.github.io/react-native/docs/images.html
Each image shows up if I just copy the require into the <Image>. I can also verify that if I instead render a <Text> element outputting this.state.on, it shows the correct value alternating.
I can't for the life of me work out what I've done wrong.
Add key to Image It will help in re-rendering image once state changed.
<Image
key={this.state.on}
source={sprite}
style={{width:16, height:20}}
/>