Working with multiple DatePickers in React Native Application - reactjs

I am new to React Native but have been searching for days so if this is easy please let me off the hook.
I have this component:
<DatePicker
signInDate={this.state.signInDate}
mode="date"
placeholder="select date"
format="DD-MM-YYYY"
minDate="01-01-1950"
maxDate="01-01-2050"
androidMode="spinner"
showIcon={false}
onDateChange={this.onDateChange('signInDate')}
/>
Which uses this class:
export default class CPT extends Component {
constructor(props) {
super(props);
this.state = {
userName: '',
isModalVisible: false,
signInDate: "01-01-2000",
startPump: "01-01-2000",
endPump: "01-01-2000",
signOut: "01-01-2000",
equipmentUsed: '',
}
}
onDateChange = (state) => (event, value) => {
this.setState({
state: value });
}
Whenever I update the date the value does change however the display value does not and I can't figure out what is going wrong.
I am stuck please, if you can point me in the right direction or tell me what I am doing wrong that would be greatly appreciated.
Basically I am going to have multiple DatePickers in this popup and will submit them to a DB or a web service when I am done when they hit submit.
I can post the rest of the code if needed.

First suggestion is that try using React-Native-Community-Date-Picker
and seems like there are some mismatch between your DatePicker props and your state attributes.
for example if you want to change signInDate in your state then your setState should look something like this this.setState({ signInDate: value }); and onDateChange would look like onDateChange={this.onDateChange}

Related

How to handle multiple material-UI Popovers [React.js]?

My app has multiple Popover components, I know how to handle the state of one Popover component, using something like this:
class App extends Component {
constructor(props) {
super(props);
this.state = { pop_open: false };
}
handleProfileDropDown(e) {
e.preventDefault();
this.setState({
pop_open: !this.state.pop_open,
anchorEl: e.currentTarget,
});
}
handleRequestClose() {
this.setState({
pop_open: false,
});
};
render() {
return (
<div>
<button type="submit" onClick={this.handleProfileDropDown.bind(this)} >My Customized PopOver</button>
<Popover
open={this.state.pop_open}
anchorEl={this.state.anchorEl}
onRequestClose={this.handleRequestClose.bind(this)}
>
{"content"}
</Popover>
</div>
);
}
}
But for more than one Popover, I do not know how to do that, should I create a state for each Popover? Sorry for the question but I am new to the frontend world.
note: kindly do not use hooks in your answer.
An internal state is a good option when only the Component is going to modify it. It keeps the logic simple and inside the same block of code. On the other hand managing the state from outside of the Component lets other components read its values and modify them. This is a common approach when using Redux or Context, where there is a global app state. This state is meant for properties that several Components need to read/write to.
Which to use when is a design decision and depends on each situation. In my opinion each Component should handle its own state when possible. For example, when values are only going to be modified by it, or a children Component. Having an external state makes sense when multiple Components are going to read or modify it, or when the state values need to be passed several levels deep in the hierarchy.
In the example you propose I can see that the Popover is working with an internal state. This can work and you can use the Component several times and it will carry all the logic inside. If you rename the Components you can see more easily what I mean. I dont know exactly how the Component with the button works but this is to make the explanation clear:
class Popover extends Component {
constructor(props) {
super(props);
this.state = { is_open: false };
}
open = () => {
this.setState({
is_open: true
});
}
close = () => {
this.setState({
is_open: false
});
}
toggle = () => {
this.setState(prevState => ({
is_open: !prevState.is_open
}));
}
render() {
return (
<div>
<button onClick={this.toggle}>
Open
</button>
{this.state.is_open && <PopoverContent />}
</div>
);
}
}
If you need further explanation or something is not clear, let me know.

How to conditionally render component in <Field> of redux-form

In my code, was trying to render a <DatePicker> in <Field> component of Redux Form, via a function called renderDatePicker(). This function is linked to handleClick() function where the state variable isOpen is set to true.
So ideally, onClick should render the <DatePicker> as it is set to visible. But code doesn't update anything. Where am I doing wrong here?
Note: Rendering <DatePicker> alone directly without the help of <Field component=...>, works fine.
For debugging, complete code is in CodeSandbox,
SimpleForm.js
import React from "react";
import { reduxForm } from "redux-form";
import { Field } from "redux-form";
import DatePicker from "react-mobile-datepicker";
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date(),
isOpen: false
};
this.handleClick = this.handleClick.bind(this);
}
renderDatePicker = () => (
<DatePicker
value={this.state.time}
isOpen={this.state.isOpen}
onSelect={this.handleSelect}
onCancel={this.handleCancel}
/>
);
handleClick() {
this.setState({ isOpen: true }, function() {
console.log(this.state.isOpen);
});
}
handleCancel = () => {
this.setState({ isOpen: false });
};
handleSelect = time => {
this.setState({ time, isOpen: false });
};
render() {
return (
<div>
<button className="select-btn" onClick={this.handleClick}>
select time
</button>
<Field
name="date"
type="date"
component={this.renderDatePicker}
label={"date"}
/>
</div>
);
}
}
export default reduxForm({
form: "simple" // a unique identifier for this form
})(SimpleForm);
The reason for this behavior lies in the implementation of react-form's Field component. It does a shallow compare of all its properties to decide whether it should rerender. You can change your component's state as much as you like, the reference to this.renderDatePicker won't change.
Field passes properties including an onChange handler and the current value into the field's component stateless function call to notify of changes, but this doesn't really apply here because your toggle button is outside of the field.
So one option that comes to my mind is to move your button into the rendered field and then call onChange(!value).
The easier yet dirtier option would be to use an arrow function in your component property: component={() => this.renderDatePicker()} - this instance changes with every re-render of your SimpleForm (i.e. if the state changes), so it comes with a cost, but depending on the complexity of your application the cost is negligible. To mitigate the impact, you could implement shouldComponentUpdate (just like redux-form's Field does) to decide whether it should rerender or not, based on the current and next isOpen state.
Check this bit in redux-form for more details: https://github.com/erikras/redux-form/blob/master/src/createField.js#L44

How is the localStorage is used within react.js?

Hello my question is simple. How can I save a single value to a localStorage; what data type should it be before it is stored. After I read 2 articles on localstorage with react and 4 answers on StackOverflow I still can't assimilate myself because the examples where on how to persist the whole state. Didn't find a documentation for react and localstorage also if someone give me a link it will be great. I wrote this code just for the example. Thank you in advance.
class List extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
}
}
componentDidMount() {
this.setState({
name: localStorage.getItem('name')
})
}
changeName = e => {
this.setState(prevState => ({
name: 'someName'
}));
localStorage.setItem('name', this.state.name);
}
render() {
return (
<Container>
<Row>
<Col sm={12}>
<div>{this.state.name}</div>
<button onClick={this.changeName}>change</button>
</Col>
</Row>
</Container>
)
}
}
export default List
There are a few NPM packages like:
https://www.npmjs.com/package/reactjs-localstorage
and
https://www.npmjs.com/package/react-use-localstorage
These should help.
In your changeName function you are setting state and after that setting the same state in localStorage which won't work in your case. This is because setState is async function, so it will take some time to execute and in that time your next code will get execute. In this scenario your localStorage will get empty value (first time) / previous value.
To make it correct you can use callback in setState like,
this.setState({name: 'someName'},
() => {localStorage.setItem('name', this.state.name)} //callback
);
Now you can have update value in localStorage every time.

React Datepicker input state not changing?

I have a multi-step form with child form components. On one of the components, I'm trying to implement YouCanBookMe DatePicker.
Now, when I try to update the state of datepicker's value like I do with other regular text inputs, the state does not get updated. If I typed the date, the state gets updated, but not when I actually select the date from the picker. I'm really clueless why. Can any of you point out why it doesn't?
Your help is greatly appreciated. I'm new to React and I've tried 3 different Datepicker libraries and I'm slowly going insane, because none seems to work or I'm not able to transform it to a Parent-Child structure. Thanks!
Parent:
constructor(props) {
super(props);
this.state = {
wants_interview_date: moment().format("DD-MM-YYYY")
}
}
handleChange(field) {
return (evt) => this.setState({ [field]: evt.target.value });
}
render(){
return <FormStep8
wants_interview_date={this.state.wants_interview_date}
onDateChange={this.handleChange('wants_interview_date')} />;
}
Child Component:
render() {
<Datetime
timeFormat={false}
dateFormat="DD-MM-YYYY"
inputProps={{id: 'wants_interview_date', onBlur: this.props.onDateChange, value: this.props.wants_interview_date}} //To get the regular HTML input props
/>
}
The good friends at Reactiflux helped me solve the issue. Apparently Moment.js was returning an Object on handleChange and therefore the state was not showing anything. The output needed to use the _d Moment.js method. Here is the correct handleChange method:
handleDateChange(field) {
return evt => {
const value = evt._d;
this.setState({ wants_interview_date: value });
};
}
this code snippet works fine for me, import DateTime (capital T)
import DateTime from 'react-datetime';
<DateTime name="newapp_time"
onChange={(e) => { this.setState({ newapp_time: moment(e).toJSON() }) }} />
the result is a timestamp in this case

react-switch-button can NOT updated by setState

i am newbie in React and recently kick start learning and playing around some third-party components. One trying is (http://gfazioli.github.io/react-switch-button/#demo)
Thus, very soon encounter a silly problem (may be just i can't figure it out how). On below sample, i just can't update the SwitchButton to false state to true. Suppose i try using the button click to trigger the update on SwitchButton but i can't just make it work.
The 'checked' property is String type, tried ('true'|'false'|'checked'|'') or even getting bk to use Boolean but still NO luck, also can NOT see any other property that it could trigger an update on SwitchButton
Grateful if anyone could help a newbie. Many Thanks
import React from 'react'
import SwitchButton from 'react-switch-button'
import 'react-switch-button/dist/react-switch-button.css'
export default class Demo extends React.Component {
constructor() {
super();
this.state = {
testChecked: 'false'
};
this.onButtonClick = this.onButtonClick.bind(this);
}
componentDidMount() {
console.log(this.state.testChecked)
}
onButtonClick(){
this.setState({
testChecked: 'true'
});
console.log(this.state.testChecked);
}
render() {
return(
<div>
react-switch-button
<br/><br/>
<input type='button' value='click' onClick={this.onButtonClick} />
<br/>
{this.state.testChecked}:
<SwitchButton name='switch-1' defaultChecked={false} checked={this.state.testChecked} />
</div>
);
}
}
Looks like the property checked is not being used as far as I can see it in the source here https://github.com/gfazioli/react-switch-button/blob/master/src/react-switch-button.js
With that in mind you want to use the defaultChecked props for switching the state e.g.
<SwitchButton name='switch-1' defaultChecked={this.state.testChecked} />
It's from type React.PropTypes.bool and not React.PropTypes.string you have change your state testChecked to that.

Resources