I just want to clear the state when you move to any other screen in my class component when I'm using navigation v6 (I saw some coments about function component but not class), so I will explain briefly
I did a clean state function in my Body component
class InputBody extends Component {
constructor(props) {
super(props);
this.state = {
fields: JSON.parse(this.props.route).message,
};
}
reset () {
this.setState({});
}
render() {
return (
<Fragment>
{Object.keys(JSON.parse(this.props.route).message).length > 0 ? (
<FieldArraysForm all={JSON.parse(this.props.route).message} resetForm={reset} native={this.props} />
) : (
<ActivityIndicator size="large" color="#eb6b09" />
)}
</Fragment>
);
}
}
And then I call it in my fields array component
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
class FieldArraysForm extends Component {
render() {
const {handleSubmit} = this.props.native;
// event listener
const getFields = async (values) => {
return sleep(500).then(() => {
console.log(JSON.stringify(values))
this.props.resetForm();
})
}
return (
<Form>
{this.props.all.map((item) => (
<Field
key={item._id}
name={`customInput.${item._id}`}
component={RenderField}
label={item.field}
type={item.typeFieldAltText}
/>
))}
<View>
<TouchableOpacity onPress={handleSubmit(getFields)}>
<Text>Save Form</Text>
</TouchableOpacity>
</View>
</Form>
);
}
}
Render field function component
class RenderField extends Component {
render() {
return (
<Fragment>
<Texto>{this.props.label}</Texto>
<TextInput
onChangeText={this.props.input.onChange}
{...this.props.input}
keyboardType={this.props.type}
/>
</Fragment>
);
}
}
So how can I call this.prop.reset() on screen change using class component with react navigation v6 ?
Related
Diet.js
export class Diet extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
};
this.addToList = this.addToList.bind(this);
}
addToList(item) {
const list = [...this.state.list, item];
this.setState({ list });
}
render() {
<FoodCreate addToList={this.addToList} />
return (
<FoodList items={this.state.list} />
)}
FoodCreate
export class FoodCreate extends Component {
constructor(props) {
super(props);
this.state = {
FoodName: "",
calories: 0,
};
}
render() {
return (
<Button transparent>
<Icon
name="checkmark"
style={{ fontSize: 25, color: "red" }}
onPress={() => this.props.addToList(FoodName, calories)}
/>
</Button>
<TextInput
placeholder="Food Name"
placeholderTextColor="white"
style={styles.inptFood}
value={FoodName}
onChangeText={(FoodName) => this.setState({ FoodName: FoodName })}
/>
<TextInput
placeholder="Calories"
placeholderTextColor="white"
style={styles.inptMacros}
keyboardType="numeric"
value={calories}
maxLength={5}
onChangeText={(calories) => this.setState({ calories: calories })}
/>
FoodList
export class FoodList extends Component {
render() {
return (
<Content>
<List>
<ListItem itemDivider>
<Text>Food</Text>
{this.props.items.map((item, index) => {
return (
<ListItem key={index}>
<Text>{item.FoodName}</Text>
<Text>{item.calories}</Text>
</ListItem>
);
})}
</ListItem>
</List>
</Content>
);
}
}
export default FoodList;
Hi, I'm new to programming and React Native, so I'm trying to create a Grocery List by letting the user type FoodName and Calories and pressing the Icon: Check in FoodCreate page, and List it in the FoodList page, at the moment when I run the code gives me back an error: _this2.props.addToList is not a function, I've tried many solutions but I'm not sure where the error is.
class FoodCreate extends Component {
render() {
return (
<Button title="aaa" onPress={() => this.props.addToList('name')}></Button>
);
}
}
export default class Diet extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
};
this.addToList = this.addToList.bind(this);
}
addToList(item) {
const list = [...this.state.list, item];
this.setState({list});
}
render() {
return <FoodCreate addToList={this.addToList} />;
}
}
I use the above code and didn't get the error
But I think you can have a better code
Don't use this.addToList = this.addToList.bind(this);, you can convert addToList to arrow function and remove this line
addToList = item => {
const list = [...this.state.list, item];
this.setState({list});
};
import React, { useState } from 'react';
import CreateProject from './CreateProjectWithName';
function Enhanced(WrappedComponent) {
// ...and returns another component...
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
render() {
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
const Wrapper = (props) => {
const Comp = Enhanced(<CreateProject />);
return (
<div>
<Comp />
<div>
{/* <button onClick={() => updateView()} /> */}
</div>
</div>
);
};
This code block just won't work. What am I doing wrong? Which principal fundamental of React am I missing out on? What is the correct way of rendering an HOC?
The HOC takes in a component reference what you are providing it is an instance when you use it like
const Comp = Enhanced(<CreateProject />);
The correct way would be
const Comp = Enhanced(CreateProject);
Also for performance reasons and for proper execution of lifecycle you must create a wrapped component with HOC outside of your component
const Comp = Enhanced(CreateProject);
const Wrapper = (props) => {
return (
<div>
<Comp />
<div>
{/* <button onClick={() => updateView()} /> */}
</div>
</div>
);
};
function Enhanced(WrappedComponent) {
// ...and returns another component...
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
render() {
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
const Wrapper = (props) => {
const Comp = Enhanced(CreateProject );
return (
<div>
<Comp />
<div>
{/* <button onClick={() => updateView()} /> */}
</div>
</div>
);
};
I'm trying to get the value of child component yet not successful. Here what I am working on ...
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} handle={handle}/>
</div>
</div>
);
};
export default Slider;
Main App.js
import Slider from '.....'
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
render() {
return(
<Slider onChange={this.state.value} />
)
}
}
I am looking to get the value to be updated to this App.js state as the slider is being dragged. onChange is not updating the state. How should I modify so that slider value gets updated on this.state.value.
The Slider component from rc-slider has an onChange prop event which is a function. You need to pass this method to slider and update the state instead of just passing the state value
import React from "react";
import Tooltip from "rc-tooltip";
import Slider, { Range } from "rc-slider";
const Handle = Slider.Handle;
const handle = props => {
const { value, dragging, index, ...restProps } = props;
return (
<Tooltip
prefixCls="rc-slider-tooltip"
overlay={value}
visible={dragging}
placement="top"
key={index}
>
<Handle value={value} {...restProps} />
</Tooltip>
);
};
const Slider = props => {
return (
<div>
<div style={{ width: 300, margin: 30 }}>
<p>{this.props.title}</p>
<Slider min={0} max={10} defaultValue={5} onChange={props.onChange} handle={handle}/>
</div>
</div>
);
};
export default Slider;
class App extends Component{
constructor(props){
super(props);
this.state = {
val: 0
}
}
onChange=(value) => {
this.setState({val: value});
}
render() {
return(
<Slider onChange={this.onChange} />
)
}
}
Here is the Live code
https://codesandbox.io/s/n9y97y55kp
Let me know if you have any doubts
You just have to pass the event from child to parent component to update the values.
according to rc-slider document, you should pass a function to Slider onChange.
import Slider from '.....'
class App extends Component {
constructor(props) {
super(props);
this.state = {
val: 0
}
}
handleSliderChange = (value) => {
console.log(value) // maybe a string or a object
this.setState({val: value})
}
render() {
return (
<Slider onChange={this.handleSliderChange} />
)
}
}
above code should work
Disclaimer : I'm new to RN. I have already tested multiple solutions from other similar questions without success so far.
I have a Parent that render two Childrens like this
export default class ParentComponent extends Component {
constructor(props) {
super(props)
}
render() {
return (
<View>
<Foo name="a" ref={foo => {this.foo = foo}} {...this.props} />
<Text>-----------</Text>
<Foo name="b" />
<Text>-----------</Text>
<Button
onPress={this.foo.myFunction()}
title="Start"
color="#841584"
/>
</View>
)
}
}
My class Foo has a function inside it that start some process :
class Foo extends Component {
myFunction(){
// Some stuff here
}
}
How can I call this myFunction for my Child when I press on the Button ? Optionally, is it possible with only one onPress, to call the function for both Child and avoid creating two Button for each Child ?
You can use refs
https://reactjs.org/docs/refs-and-the-dom.html
Example:
class Parent extends Component {
render() {
return (
<View>
<Child ref={instance => { this.child = instance; }} />
<TouchableOpacity onPress={() => { this.child.clicked(); }}>
<Text>Click</Text>
</TouchableOpacity>
</View>
);
}
}
class Child extends Component {
clicked() {
alert('clicked');
}
render() {
return (
<Text>Hello</Text>
);
}
}
Hope it helps
Basically what I did is to call a local function when onPress and change the state of the Parent. I pass this state to the Child during its creation. And since the Child are updated (if needed) when the Parent's state change this do the trick.
export default class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
activity: false
}
}
onButtonPress = () => {
this.setState({
activity: !this.state.activity
});
}
render() {
return (
<View>
<Foo name="a" activity={this.state.activity} />
<Text>-----------</Text>
<Foo name="b" activity={this.state.activity} />
<Text>-----------</Text>
<Button
onPress={this.onButtonPress}
title="Start"
color="#841584"
/>
</View>
)
}
}
class Foo extends Component {
myFunction(){
// Some stuff here
}
componentWillReceiveProps(newProps) {
if (newProps.activity === true) {
this.myFunction();
}
}
}
It's better to do myFunction logic inside ParentComponent and setState the data which can be passed into child ie:Foo.
constructor(props) {
super(props);
this.state = {
fooData: initialValue,
}
}
myFunction = () => {
// Some stuff here
this.setState({ fooData: someValue })
}
render() {
return (
<View>
<Foo name="a" data={this.state.fooData} {...this.props} />
<Text>-----------</Text>
<Foo name="b" data={this.state.fooData}/>
<Text>-----------</Text>
<Button
onPress={this.myFunction}
title="Start"
color="#841584"
/>
</View>
)
}
and you can make the changes inside Foo accordingly
class Foo extends Component {
render() {
const { data } = this.props;
return(
//Use data here to make change
)
}
}
I am trying to make an application using reactjs.below is the code which present in my main app.js:
class App extends Component {
return (
<div>
<ExampleTable
header={() => <TopBar/>}
/>
<AddExampleModal/>
<ChartModal/>
<CompatibilityAlert/>
</div>
)
}
}
where Top Bat,AddExampleModal , ChartModal and CompatibilityAlert are loaded from other js files.
Chartmodal contains:
class ChartModal extends Component{
constructor(props){
super(props)
}
render(){
return(
<Modal
onOk={()=>console.log('ok')}
onCancel={()=>console.log('cancel')}
visible={true}
okText={'ok'}
cancelText={'cancel'}
confirmLoading={false}
title="Intent distribution chart"
>
<h1>HOWDY</h1>
<TreeMap
data={chartData}
width={400}
valueUnit={'count'}
/>
</Modal>
)
}
}
Topbar contains :
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
// onClick={() => changechartshow()}
>
Show Graph
</Button>
)
}
}
The thing is that in the app file,i want to toggle the visibility of chartmodal using the button in the topbar.
App
class App extends Component {
constructor() {
this.state = {
isVisible: true
}
}
toggleVisibility = () => this.setState({isVisible: !this.state.isVisible})
render () {
const {isVisible} = this.state;
return (
<div>
<ExampleTable
header={() => <TopBar toggleVisibility =
{this.toggleVisibility.bind(this)}
/>}
<AddExampleModal/>
<ChartModal isVisible={isVisible}/>
<CompatibilityAlert/>
</div>
);
}
}
TopBar
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
onClick={() => this.props.toggleVisibility()}
>
Show Graph
</Button>
)
}
}
ChartModal - Pass the state to visible attribute
class ChartModal extends Component{
constructor(props){
super(props)
}
render(){
return(
<Modal
onOk={()=>console.log('ok')}
onCancel={()=>console.log('cancel')}
visible={this.props.isVisible}
okText={'ok'}
cancelText={'cancel'}
confirmLoading={false}
title="Intent distribution chart"
>
<h1>HOWDY</h1>
<TreeMap
data={chartData}
width={400}
valueUnit={'count'}
/>
</Modal>
)
}
}
You can add a state in your App component and pass an handler to update the state from the TopBar component. Based on this state you can toggle the visibility of ChartModal.
class App extends Component {
state = {
isVisible: true
}
toggleVisibility = () => {
this.setState(prevState => ({isVisible: !prevState.isVisible}))
}
return (
<div>
<ExampleTable
header={() => <TopBar toggleVisibility={this.toggleVisibility}/>}
/>
<AddExampleModal/>
{this.state.isVisible ? <ChartModal/>: null }
<CompatibilityAlert/>
</div>
)
}
}
Now in your TopBar you will call this function as
class TopBar extends Component {
render{
return (
<Button
style={styles.button}
type='primary'
onClick={() => this.props.toggleVisibility()}
>
Show Graph
</Button>
)
}
}
Read the React docs here on Lifting the state up for a detailed explanation