react-native
(componentWillUpdate, componentWillReceiveProps)
swipe function app.
Warning: componentWillReceiveProps is deprecated and will be removed in the next major version. Use static getDerivedStateFromProps instead.
Warning: componentWillUpdate is deprecated and will be removed in the next major version. Use componentDidUpdate instead. As a temporary workaround, you can rename to UNSAFE_componentWillUpdate.
The YellowBox.ignoreWarnings method is not necessary.
I'll ask you to update the code.
How should I solve it?
//git component
const renderPagination = (index, total, context) => {
return (
<View style={styles.paginationStyle}>
<Text style={{ color: 'grey' }}>
<Text style={styles.paginationText}>{index + 1}</Text>/{total}
</Text>
</View>
)
}
export default class App extends Component {
constructor(props) {
super(props);
this.onPressNext = this.onPressNext.bind(this);
this.onPressPrev = this.onPressPrev.bind(this);
this.state = {
indexPage: 0
}
}
onPressPrev = () => {
const { indexPage } = this.state;
if (indexPage > 0) {
this.refs.swiper.scrollBy(-1);
}
}
onPressNext = () => {
const { indexPage } = this.state;
if (indexPage < 4) {
this.refs.swiper.scrollBy(1);
}
}
render() {
return (
<View style={styles.container}>
<View style={{flex:0.1, backgroundColor: 'green'}}>
<Text>NAVTEX</Text>
</View>
{/* {git component} */}
<Swiper
style={styles.wrapper}
onIndexChanged={indexPage => this.setState({ indexPage })}
renderPagination={renderPagination}
showsButtons={false}
loop={false}
ref={'swiper'}
>
<View style={styles.slide}>
<Text style={styles.text}>2</Text>
</View>
<View style={styles.slide}>
<Text style={styles.text}>2</Text>
</View>
<View style={styles.slide}>
<Text style={styles.text}>3</Text>
</View>
<View style={styles.slide}>
<Text style={styles.text}>4</Text>
</View>
<View style={styles.slide}>
<Text style={styles.text}>5</Text>
</View>
</Swiper>
<View style={styles.buttoncontainer}>
<Button
style={{with:75}}
onPress={this.onPressPrev}
title="Previous">
</Button>
<Button
onPress={this.onPressNext}
title="Next">
</Button>
</View>
</View>
);
}
}
The warning is not being caused by your code. It's being caused by the react-native-swiper library. I looked at their code on GitHub and in the src/index.js file on line 199, they invoke componentWillReceiveProps(). It's not something you need to worry about and is the responsibility of the library maintainer.
Screenshot of search on GitHub
I can not seem to comment yet so I will just leave this answer here. I had the same problem. As you mentioned on the comments of hongs answer, you have not used componentWillUpdate and componentWillReceiveProps but one of the modules you installed maybe using them. In my case it was react-moment or momentjs which was using componentWillUpdate. Also as mentioned above, it will be removed from react-native in the next upcoming major update so it is highly recommended to use the alternatives.
Alternatively you could disable the warn boxes. But this is not recommended to do so on development environment. If you want you could disable warns by putting this console.disableYellowBox = true; in your root component.
And as a side note, please move all your styles on to the stylesheet and not inline styling as later on this will become a hassle to change again.
Happy Coding :)
Update: As you have mentioned you use react-native-swiper and surely enough it does use both componentWillReceiveProps and componentWillUpdate. As seen here.
on line 199: componentWillReceiveProps(nextProps)
on line 217: componentWillUpdate(nextProps, nextState)
And yes there is nothing wrong with your code as long as you don't use those methods. Please use the updated methods. And as for react-native-swiper, the devs will probably update it before the removal on the next major update so you can do an npm update on the next major release and check.
Related
I am trying to make a multiple choice test with a few questions using React Native package 'react-native-app-intro-slider'. The problem was that this package was not rerendering the items when something changes, state for example. I found a similar or refactored package called 'react-native-app-intro-slider-rerender-on-prop-change' that did the same thing but rerendered items on a state change. But the problem is that it does not render the Done button at last slide.
The last package i used was this :
import AppIntroSlider from 'react-native-app-intro-slider-rerender-on-prop-change';
The render method for the 'MCTContainer' (Multiple Choice Container) class is :
render() {
if (this.state.showRealApp) {
this.props.navigation.navigate('TopicGroupDetails', { topicGroup: this.state.topicGroup });
return null;
} else {
const questions = this.state.questions;
return (
<AppIntroSlider
renderItem={this._renderItem}
slides={questions}
onDone={this._onDone}
onSkip={this._onDone}
activeDotStyle={{ backgroundColor: '#039BE5' }}
showPrevButton
showNextButton
showSkipButton
showDoneButton
renderPrevButton={this._renderPrevButton}
renderNextButton={this._renderNextButton}
renderSkipButton={this._renderSkipButton}
renderDoneButton={this._renderDoneButton}
/>
)
}
}
and its renderDoneButton method is like following :
_renderDoneButton = () => {
return (
<View style={styles.buttonCircle}>
<Icon
name="check"
color="#039BE5"
size={24}
style={{ backgroundColor: 'transparent' }}
/>
</View>
);
};
This is actually the same, exactly the same as I used for the component 'SliderComponent' where I show tutorial introductory text in multiple slides. It renders the 'done' button fine. But the only differenence is that I used package 'react-native-app-intro-slider' there, not 'react-native-app-intro-slider-rerender-on-prop-change'.
Please help me if someone has encountered such a problem. Thanx in advance ...
I finally solved it.
I just added a condition on "renderItem" function of the "AppIntroSlider", that checks whether it is the last slide. If it is it renders a button that calls "AppIntroSlider"-s "_onDone" method that completes the slide show.
_renderItem = ({item}) => {
return(
{
(this.state.isLastSlide) ?
(
<TouchableHighlight
onPress={this._onDone}
>
<View>
<Text>
COMPLETE SLIDE SHOW
</Text>
<Icon
name="check"
color="white"
size={24}
/>
</View>
</TouchableHighlight>
) :
(<View></View>)
}
)
}
I am trying to use the Switch component provided by react-native, but it doesn't toggle.
function settings(props) {
let {changeView, header} = props;
let rememberPin = false;
let toggleRememberPin = (value) => {
rememberPin = value;
};
return (
<View style={styles.appContainer}>
<View style={styles.appBody}>
<View style={{flex:1, flexDirection: 'row',justifyContent:'center',alignItems:'center',width: Dimensions.get('screen').width,backgroundColor: Colors.white}}>
<Text>Remember PIN:</Text>
<Switch
onValueChange={toggleRememberPin}
value={rememberPin}
ios_backgroundColor="#aeaeae"
trackColor={{true: Colors.customerGreen, false: '#aeaeae',}}/>
</View>
</View>
</View>
);
}
I get the Switch rendered in the View, I can touch it and it moves from OFF to ON, but suddently it come back to OFF without keeping on ON state.
What's wrong?
You need to look into the core concepts of React, particularly how component state works.
In short, normal variable assignment doesn't cause a component to re-render and reflect changes. That's when you want to use the concept of state.
Here's how to do it properly:
function Settings(props) {
let {changeView, header} = props;
const [rememberPin, setRememberPin] = useState(false);
const toggleRememberPin = (value) => {
setRememberPin(value);
};
return (
<View style={styles.appContainer}>
<View style={styles.appBody}>
<View style={{flex:1, flexDirection: 'row',justifyContent:'center',alignItems:'center',width: Dimensions.get('screen').width,backgroundColor: Colors.white}}>
<Text>Remember PIN:</Text>
<Switch
onValueChange={toggleRememberPin}
value={rememberPin}
ios_backgroundColor="#aeaeae"
trackColor={{true: Colors.customerGreen, false: '#aeaeae',}}/>
</View>
</View>
</View>
);
}
I'm going back to basics with React Native, as I feel overwhelmed. I have been looking for an implementation of a reusable modal component. I'm looking for examples of a reusable Modal component in RN? Thanks in advance
You can find many examples of this on StackOverflow. Still, if you need example I can help you with one example. You have mentioned modal component in your question, right?
Your component will look like this with props. let the name be ModalComponent for this file.
render() {
const { isVisible, message, textValue } = this.props;
return (
<Modal
animationType="slide"
transparent={false}
isVisible={isVisible}
backdropColor={"white"}
style={{ margin: 0 }}
onModalHide={() => {}}>
<View>
<Text>textValue</Text>
<Text>message</Text>
</View>
</Modal>
);
}
so now in your js file you need to import this modalComponent and after that, you need to write as
<ModalComponent
isVisible={true}
textValue={'hi there'}
message={'trying to make a basic component modal'}/>
Hope this will help for you
EDIT:
Create seperate components that you want to render inside modal. for Ex: component1.js, component2.js, component3.js with props
component1.js:
render(){
const { textVal, message } = this.props
return (
<View>
<Text>{textVal}</Text>
<Text>{message}</Text>
</View>
)
}
now in ModalComponent
render() {
const { first, second, third, isVisible, component1Text, component1Message } = this.props;
<Modal
animationType="slide"
transparent={false}
isVisible={isVisible}
backdropColor={"white"}
style={{ margin: 0 }}
onModalHide={() => {}}>
<View>
{first && <component1
textValue= component1Text
message= component1Message />}
{second && <Component2 />}
{third && <Component2 />}
</View>
</Modal>
In this way, you can achieve it within the single modal.
You will make a component like this giving the parent component all the liberty to change it through props.
render() {
const { isVisible, message, textValue, animationType, backDropColor, style, onModalHide, children } = this.props;
return (
<Modal
animationType= {animationType || 'slide'}
transparent={transparent || false}
isVisible={isVisible || false}
backdropColor={backdropColor || "white"}
style={[modalStyle, style]}
onModalHide={onModalHide}>
{children}
</Modal>
);
}
Then in your parent component, you need to import this component like this:
import ModalComponent from '../ModalComponent'; //path to your component
<ModalComponent isVisible={true}>
<View>
//any view you want to be rendered in the modal
</View>
</ModalComponent>
I had a lot of troubles using react-native modal, sometimes i started the app and could not close it even when i set the isVisible prop to false, it is even worst on IOs, i did a research and these packages are not being maintained properly.
You will save a lot of time by using a top-level navigator like is recommended in the modal docs: https://facebook.github.io/react-native/docs/modal.
I tried https://github.com/react-native-community/react-native-modal but had the same problems because its an extension of the original react-native modal.
I suggest you to use the react-navigation modal as described here: https://reactnavigation.org/docs/en/modal.html#docsNav
You can refer the following code to write Modal component once and use multiple times.
Write once:
import React, { Component } from 'react';
import { View, Text, Button, Modal, ScrollView, } from 'react-native';
export class MyOwnModal extends Component {
constructor(props) {
super(props);
this.state = {
}
render() {
return(
<Modal
key={this.props.modalKey}
transparent={this.props.istransparent !== undefined ? true : false}
visible={this.props.visible}
onRequestClose={this.props.onRequestClose}>
<View style={{
//your styles for modal here. Example:
marginHorizontal: width(10), marginVertical: '30%',
height: '40%', borderColor: 'rgba(0,0,0,0.38)', padding: 5,
alignItems: 'center',
backgroundColor: '#fff', elevation: 5, shadowRadius: 20, shadowOffset: { width: 3, height: 3 }
}}>
<ScrollView contentContainerStyle={{ flex: 1 }}>
{this.props.children}
</ScrollView>
</View>
</Modal>
);
}
}
Now,
You can call your Modal like following example: (By doing this, you avoid re-writing the Modal and its outer styles everytime!)
Example
<MyOwnModal modalKey={"01"} visible={true} onRequestClose={() =>
this.anyFunction()} istransparent = {true}>
<View>
// create your own view here!
</View>
</MyOwnModal>
Note: If you are in using different files don't forget to import , and also you can pass the styles as props.
(You can create/customise props too based on your requirement)
Hope this saves your time.
Happy coding!
I am a contributor of react-native-use-modal.
This is an example of creating a reusable modal in a general way and using react-native-use-modal: https://github.com/zeallat/creating-reusable-react-native-alert-modal-examples
With react-native-use-modal, you can make reusable modal more easily.
This is a comparison article with the general method: https://zeallat94.medium.com/creating-a-reusable-reactnative-alert-modal-db5cbe7e5c2b
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>
Just started learning react-native,
I have created one separate file flexdemo.js and created component as below:
import React, { Component } from 'react';
import { View } from 'react-native';
export default class FlexibleViews extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: "powderblue" }}> </View>
<View style={{ flex: 2, backgroundColor: "skyblue" }}> </View>
<View style={{ flex: 3, backgroundColor: "steelblue" }}> </View>
</View>
);
}
}
and App.js file is as below:
import React, { Component } from 'react';
import {
AppRegistry,
Platform,
StyleSheet,
Text,
View, Image
} from 'react-native';
// import Bananas from './src/banana';
// import LotsOfStyles from './src/styledemo'
import FlexibleViews from './src/flexdemo';
export default class App extends Component {
render() {
return (
// <Bananas name = "Tapan"/>
<View>
<FlexibleViews />
</View>
);
}
}
That gives me this error:
Now if I try to run the code by adding flexdemo.js code into App.js then everything works fine.
Changed The App.js like this:
import React, { Component } from 'react';
import { AppRegistry, View } from 'react-native';
export default class FlexDimensionsBasics extends Component {
render() {
return (
// Try removing the `flex: 1` on the parent View.
// The parent will not have dimensions, so the children can't expand.
// What if you add `height: 300` instead of `flex: 1`?
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'powderblue'}} />
<View style={{flex: 2, backgroundColor: 'skyblue'}} />
<View style={{flex: 3, backgroundColor: 'steelblue'}} />
</View>
);
}
}
Remove comments inside component.
I want to give a more general answer here, because there can be several reasons for the issue returning the same error message. The three I have seen the most:
1. Comments might be the cause. But instead of removing comments make
them work:
In the return()-part, variables need to be wrapped in {} like
{this.state.foo} so wrapping the comments works fine...
return(
<Text> This works {/* it really does */}</Text>
);
...as long as they are not the first or last element in the return statement:
return(
{/* This fails */}
<Text> because the comment is in the beginning or end </Text>
{/* This also fails */}
);
2. Conditional rendering might be the cause. If myCheck is undefined or
an empty string this can fail:
const myCheck = ""; /* or const myCheck = undefined */
return(
{myCheck && <MyComponent />}
);
but adding double negation !! works:
const myCheck = ""; /* or const myCheck = undefined */
return(
{!!myCheck && <MyComponent />}
);
3. Whitespaces (or actually any strings) within a component can cause
this, if not in a <Text>-Component:
Text in a View for example:
/* This fails */
return(
<View>it really does</View>
);
But also the tiny space between two components:
/* <View>*Space*<Text> fails: */
return(
<View> <Text>it really does</Text> </View>
);
But works if in a newline:
return(
<View>
{/* This works */}
<Text>surprisingly it does</Text>
</View>
);
Unfortunately these pitfalls do not always lead to errors. Sometimes they work. I guess this depends on which of all those many tools/libraries/components you use and their versions in your app.
I was able to reproduce the issue with the code you provided. The solution is twofold:
In your flexdemo.js file you should remove the whitespaces from within the <View> tags. They are considered as text, and text is only allowed inside a <Text> component. I'd recommend making your <View> tags self closing until they have some content, to stay away from this issue in the future, like so:
import React, { Component } from 'react';
import { View } from 'react-native';
export default class FlexibleViews extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: 'powderblue' }} />
<View style={{ flex: 2, backgroundColor: 'skyblue' }} />
<View style={{ flex: 3, backgroundColor: 'steelblue' }} />
</View>
);
}
}
This will render your components but still be faulty, as you wont see anything on the screen.
To get your flexible shades of blue to appear you'll either have to add flex to the <View> component in your App.js file or(depending on what your next steps are, I guess) remove it and render your <FlexibleViews> as the root component, since it is basically a <View> component with some children anyway.
If you have if else statement in your render() function use !! like this:
{!! (this.state.your_state) &&
<View>
<Text>Your Text</Text>
</View>
}
instead of:
{(this.state.your_state) &&
<View>
<Text>Your Text</Text>
</View>
}
I downgrade react native version, then I got a different error, basically what it was I had a simple string within a view, something like this:
<View>
MyComponent
</View>
I had to wrap the string with a text component like this:
<View>
<Text>MyComponent</Text>
</View>
hope that helps
<View style={{ flex: 1 }}>
<Text style={{ flex: 1, backgroundColor: "powderblue" }}> </Text>
<Text style={{ flex: 2, backgroundColor: "skyblue" }}> </Text>
<Text style={{ flex: 3, backgroundColor: "steelblue" }}> </Text>
</View>
Make use Component hierarchy should be maintain, for example all components like Text, ListView, TextInput etc should be wrapped inside the parent component that is View.
lets see the below example :
< View >
< Text >
CORRECT
< / Text >
< / View >
Make sure all the Component tag should be closed properly.
Make sure unnecessary semicolons should be removed from the react native layout components & functions.
https://www.skptricks.com/2018/08/react-native-cannot-add-child-that.html
This error is usually from one of below mistakes
Remove unnecessary comments and remove comments from return function.
check for proper variable name.
check for unintended semicolon or any wrong syntax
Delete the comment in the return block "// "
I encountered the same problem when I accidentally add a ';' in the return block, the iOS is work well, but the Android has this bug information
In my case I had small () brackets around one of my view which was causing error.
({renderProgress()})
Removing small brackets worked for me.
{renderProgress()}
In my case I had a condition in my render function that resulted in evaluating 0.
It seems that 0 && 'some jsx' breaks in newer versions of react native.
Error Example:
render(){
return <View>
{this.state.someArray.length && <View>...</View>}
</View>
}
Although this should be valid javascript and works in react since 0 is falsey, It crashes in react native, not sure why but it works with a little refactoring as:
Working Example:
render(){
return <View>
{this.state.someArray && this.state.someArray.length> 0 &&
<View>...</View>}
</View>
}
Remove semi-colon when rendering a method in
<View style={styles.container}>
{this.renderInitialView()} //semi-color should not be here
</View>
I have encountered the same issue just now and solved it by removing the comments that I have made while editing the project in android studio and over there the comment's shorotcut just adds /* and */ but actually for react native the commented code should be enclosed with starting and end of curly braces, for example following would be an invalid comment:
/*<Text style={styles.pTop}>
{
this.state.response.map((index, value) => {
return index.title;
})
}
</Text>*/
And the following will be a valid one:
{/*<Text style={styles.pTop}>
{
this.state.response.map((index, value) => {
return index.title;
})
}
</Text>*/}
you see there is just one minor difference of enclosing the comment in curly braces.
This error also occurs if you have comments in your render() return() function. Remove all comments in your return function when rendering JSX
In my case I had written <TextInput> in the <Text> tag.
Below is wrong. It will give error for child.
<text>
<TextInput style={styles.textinput}
textcolor
placeholder = 'user id'
placeholderTextColor = 'gray'
/>
</Text>
solution.
<Text> hello </Text>
<TextInput style={styles.textinput}
textcolor
placeholder = 'user id'
placeholderTextColor = 'gray'
/>
you have to write separate tag.
So any tag you have written in another tag this error can come.