How do you update the render of a react native class when it extends component?
I have tried using setState that works in the "first screen class" and in a menu/navigator class that acts as a shell of the application, but when I try to use this functions in an other class that is called from the shell I get the errormessage "Warning: getInitialState was defined on..., a plain javascript class..." and when trying to use setState or forceUpdate the message "Warning forceUpdate/setState (and so on) Can only update a mounted or mounting component.
Is there a solution to re-render by code?
import React, { Component, PropTypes } from 'react';
import { View, Text, TouchableHighlight } from 'react-native';
export default class testClass extends React.Component {
constructor(props) {
super(props)
}
getInitialState() {
return {
isLoading: true,
PackageNo: '',
PackageNoSeq: '',
hasError: false,
errorMessage: '',
};
}
render() {
return (
<View>
<Text>Test</Text>
<TouchableHighlight onPress={this.go.bind(this)}>
<Text>Go to Apple</Text>
</TouchableHighlight>
</View>
)
}
go() {
console.log("go to other");
this.props.navigator.push({ screen: 'OtherTest' });
}
}
Simple highlight . React.createClass is a traditional way to declare/create a component class in React. getInitialState is one of React.createClass life cycle method and React team just released a small syntax sugar update to allow for better use with ES6 modules by extends React.Component, which extends the Component class instead of calling createClass.
The getInitialState function is deceased, and now you need to declare all state as a simple initialisation property in the constructor
constructor(props) {
super(props);
this.state = {
isLoading: true,
PackageNo: '',
PackageNoSeq: '',
hasError: false,
errorMessage: ''
}
}
Simply use setState method to rerender. Or pass props from the parent component.
import React, { Component, PropTypes } from 'react';
import { View, Text, TouchableHighlight } from 'react-native';
export default class testClass extends Component {
state = {
text: 'Go to Apple'
}
onPress = () => {
this.setState({text: 'Go to hell'})
}
render() {
return (
<View>
<Text>Test</Text>
<TouchableHighlight onPress={this.onPress}>
<Text>{this.state.text}</Text>
</TouchableHighlight>
</View>
)
}
}
Related
I've got an error when creating new component in React Native
I don't know what causes this error because I already declare the View component
"react-native": "0.65.1"
the code in the component
import React from 'react';
import { Text, View } from 'react-native';
import Styles from './Styles';
import CommonUtils from '../../components/base/CommonUtils';
import Constant from '../../constants/Constant';
class FrequentlyAskedQuestion extends React.Component {
navigationOptions = (route, navigation) => {
return CommonUtils.getBackNavigationHeader(route, navigation, Constant.HEADER_TITLE.FAQ, 1, false, true);
};
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() {
this.props.navigation.setOptions(this.navigationOptions(this.props.route, this.props.navigation));
}
render() {
return (
<View>
<Text>
asda
</Text>
</View>
)
}
}
export default FrequentlyAskedQuestion;
Tried exactly with your code,couldnt replicate the error
https://snack.expo.dev/#gaurav1995/gnarly-marshmallows
import React from 'react';
import { Text, View } from 'react-native';
class FrequentlyAskedQuestion extends React.Component {
navigationOptions = (route, navigation) => {
return null
};
constructor(props) {
super(props);
this.state = {
}
}
componentDidMount() {
// this.props.navigation.setOptions(this.navigationOptions(this.props.route, this.props.navigation));
}
render() {
return (
<View>
<Text>
asda
</Text>
</View>
)
}
}
export default FrequentlyAskedQuestion;
My bad, I made a mistake in the stack navigator of importing the component, it already solved
from
import FrequentlyAskedQuestion from '../features/faq/faq';
to import FrequentlyAskedQuestion from '../features/faq/Faq';
Can you help me in changing this React stateless functional component to React class based component including the withRouter and history object as given?
const Menu = withRouter(({history}) => (
<AppBar>
</AppBar>
))
export default Menu
class Menu extends React.Component {
render() {
// you can use this.props.history anywhere in the class
const { history } = this.props;
return <AppBar>...</AppBar>
}
}
export default withRouter(Menu);
First, create your class component and then, create a constructor for the class. You can then define the states required inside the constructor, something like this-
export default class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
SomeVar: xyz,
AnotherVar: undefined
}
}
render() {
return withRouter(({history}) => (
<AppBar> </AppBar>
));
}
}
I'm trying to mount a React Portal whose node is the member of current rendering component. As per shown in the below code, I've to forcefully re-render it by setting a state in the componentDidMount which seems to be an anti-pattern to me.
import React from 'react';
import PropTypes from 'prop-types';
import FormProduct from 'containers/FormProduct';
import Portal from 'shared/Portal';
class Users extends React.Component {
constructor(props) {
super(props);
this.productForm = React.createRef();
this.state = {
mounted: false,
}
}
componentDidMount() {
this.setState({ mounted: true});
}
render() {
return (
<React.Fragment>
<div className="mt-20" ref={this.productForm}></div>
{this.state.mounted && <Portal node={this.productForm.current}>
<FormProduct />
</Portal>}
</React.Fragment>
)
}
}
How can we achieve it in the first rendering?
I have an App which has a state that contains the information if the user is loggged in or not. This state is passed to a Context Provider:
App.native.js
import React, { Component } from "react";
import Orientation, { orientation } from "react-native-orientation";
import Navigator from "./navigation/Navigator";
import { createContext } from 'react';
export const LoginContext = createContext({
isLoggedIn: false,
login: () => {},
logout: () => {}
});
export default class App extends Component {
constructor(props) {
super(props);
this.login = () => {
this.setState(state => ({
isLoggedIn: true
}));
console.log("Logged in!");
};
this.logout = () => {
this.setState(state => ({
isLoggedIn: false
}));
console.log("Logged out!");
};
this.state = {
isLoggedIn: false,
login: this.login,
logout: this.logout
};
}
componentDidMount = () => {
Orientation.lockToPortrait();
};
render() {
return <LoginContext.Provider value={this.state}><Navigator /></LoginContext.Provider>;
}
}
In (almost) every screen of the App I want to show an Icon in the header, e.g.:
SearchScreen.js
import styles from './styles';
import React, { Component } from 'react';
import { Text, View,AsyncStorage } from 'react-native';
import { Button } from 'react-native-elements';
import LoginIcon from '../../components/LoginIcon'
import { StatusBar } from 'react-native'
class SearchScreen extends Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: "Suchen",
headerRight: <LoginIcon navigation={navigation} />
});
render() {
return (
<View style={styles.container}>
<StatusBar barStyle = "dark-content" hidden = {false} backgroundColor = "#338A3E" />
<Text>This is the SearchScreen.</Text>
</View>
);
}
}
export default SearchScreen;
The icon should show either a LogIn or Logout image, depending on the state of the App. I try to do that by using the Context Consumer:
LoginIcon.js
import styles from "./styles";
import React, { Component } from "react";
import { View, AsyncStorage } from "react-native";
import { Icon } from "react-native-elements";
import AntIcon from "react-native-vector-icons/AntDesign";
import {LoginContext} from "../../App.native.js";
const LoginIcon = ({navigation}) => {
return (
<LoginContext.Consumer>
{({isLoggedIn, login, logout}) => {
return (isLoggedIn ?
<Icon
name="logout"
type='material-community'
containerStyle={styles.icon}
color="white"
onPress={logout}
/>
:
<Icon
name="login"
type='material-community'
containerStyle={styles.icon}
color="white"
onPress={navigation.navigate("Login")}
/> );
}
}
</LoginContext.Consumer>
);
}
export default LoginIcon;
Now, when I login (via a LoginScreen not shown here), the state changes as expected (isLoggedIn = true), and the Icon in the Heder of the SearchScreen shows the correct "Logout" button. That is great!
But when I click this button, I get two errors:
1: Warning: Cannot update during an existing state transition (such as within 'render'). Render methods should be a pure function of props and state.
This is a riddle for me, I know I have a design flaw here but don't know how to solve it because ...well, basically everything happens inside a render function?
2) Failed prop type: Invalid prop 'onPress' of type 'boolean' supplied to 'Icon', expected 'function'.
in Icon (at withTheme.js:24) in Themed.Icon (at LoginIcon.js:22) in LoginIcon (at SearchScreen.js:12)
As far as I understand passing props to a function component is possible, but this.props should be left out when calling the prop inside the component. But it does not seem to work. How can I make that work?
I have a React component that uses default props:
class MyComponent extends Component {
constructor(props) {
console.log('props', props);
super(props);
// rest of code here
}
MyComponent .defaultProps = {
__TYPE: 'MyDateRange',
};
When I use the component, without passing any props, the console log of props shows the default props, like it should.
Now, when I want to pass an additional prop (a function in this case), like this:
<MyComponent onEnterKey={() => console.log('snuh')}/>
The console log of props only shows the onEnterKey function.
What do I have to do to allow MyComponent to use the default props and accept a function? I've tried adding another argument to the constructor of MyComponent, but that doesn't work.
I tried and this is working :
import React from "react";
import { render } from "react-dom";
class MyComponent extends React.Component {
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return null;
}
}
MyComponent.defaultProps = {
__TYPE: "MyDateRange"
};
render(
<MyComponent onEnterKey={() => console.log("snuh")} />,
document.getElementById("app")
);
You can see it here : https://codesandbox.io/s/wkw0k0j5o8
You can put the defaultProp on the class outside of the constructor like this:
class MyComponent extends Component {
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return <div> test </div>;
}
}
MyComponent.defaultProps = {
__TYPE: "MyDateRange"
};
Alternatively, you can have defaultProps be a static property on the class:
class MyComponent extends Component {
static defaultProps = {
__TYPE: "MyDateRange"
};
constructor(props) {
console.log("props", props);
super(props);
}
render() {
return <div> test </div>;
}
}