React-Dates in component using Redux - reactjs

As a newbie in React and Redux, i'm trying to use react-dates in a component.
This is my code:
import * as React from 'react';
import { connect } from 'react-redux';
import { ApplicationState } from '../store';
import * as DateState from '../store/Date';
import * as SingleDatePicker from 'react-dates';
type DateProps = DateState.DateState & typeof DateState.actionCreators;
class DatePickerSingle extends React.Component<DateProps, any> {
public render() {
let { date } = this.props;
return (
<div>
<SingleDatePicker
id="date_input"
date={this.props.date}
focused={this.state.focused}
onDateChange={(date) => { this.props.user({ date }); }}
onFocusChange={({ focused }) => { this.setState({ focused }); }}
isOutsideRange={() => false}
displayFormat="dddd LL">
</SingleDatePicker>
</div>
);
}
}
export default connect(
(state: ApplicationState) => state.date,
DateState.actionCreators
)(DatePickerSingle);
This returns the following error:
Exception: Call to Node module failed with error: TypeError: Cannot read property 'focused' of null
focused an onFocusChange should receive the "datepicker state" as far as I understand.
Docs:
onFocusChange is the callback necessary to update the focus state in
the parent component. It expects a single argument of the form {
focused: PropTypes.bool }.
I think the problem is that I inject the DateState in the DatePickerSingle component, which doesn't know about focused state.
Is it possible to use my "own" state and the state from the DatePicker together? Or what is the best approach?
I'm trying for quite a while now, and I hope someone can help me with this.
UPDATE

The answer is quite simple: this.state is null because it has not been initialized. Just add
constructor() {
super();
this.state = {
focused: false
}
}
Anything coming from redux will be passed to your component as props, you can have component state in addition to that.

Related

React Redux Component passing props not re-render

I'm using React with react-redux package and I've created a Redux component.
import React from 'react'
import { connect } from 'react-redux'
class Prova extends React.Component {
constructor(props) {
super(props)
this.state = { ...props }
}
componentDidUpdate(prevProps) {
if (prevProps.errors !== this.props.errors) {
this.setState({
errors: this.props.errors
});
}
}
render() {
const props = this.props.errors ? <div>props: {Object.keys(this.props.errors).map(prop => <div className='props'>{prop}</div>)}</div> : <>NO ERRORS</>
return (
<div>
{props}
</div>
)
}
}
function mapState(state, ownProps) {
return {
}
}
const actionCreators = {
}
const connectedProva = connect(mapState, actionCreators)(Prova)
export { connectedProva as Prova }
I'm calling this component like this:
<Prova errors={this.state.errors} />
Where errors is stored and updated in the state of the Parent component.
The problem is that errors aren't updated in the store state of redux but in the state of the component and this value is passed to the Prova component as "simple" props. But updating the Parent state doesn't re-render the Prova component.
Is it possible that using a Redux component hide the props passed? they are readed only when the Prova component is created the first time.
Thanks
EDIT:
Finally I understood the problem.
In the parent component where I was updating the errors state I wasn't destroying the prev version of errors but filling with the new data.
Now it's working changing it to:
var errors = { ...prevErrors }
Thanks

React native set state is not working

I am trying to update state in react native component.
But its getting errors, Could someone help me.
I'm using react-native-cli verions: 2.0.1
react-native verions: 0.55.4
Here is my code:
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
state = {
isDone: false
};
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
onPress={this.onAction}
/>
</View>
)
}
}
export default ToggleButton;
You have three different solutions.
Bind your function in the constructor.
Use the experimental public class fields syntax.
Pass a lambda to executing your function.
The problem is that you're loosing the reference to this, because the function is not executed in the original context, so this.setState is not a function, but a undefined.
In this page there are examples for all of the approaches: https://reactjs.org/docs/handling-events.html
Change
onPress={this.onAction}
to
onPress={this.onAction.bind(this)}
Check: this
Below is the solution
import React, { Component } from 'react'
import {
Button,
Text,
View,
} from 'react-native';
export class ToggleButton extends Component {
// Add state in constructor like this
constructor(props){
super(props);
this.state = {
isDone: false
};
}
onAction() {
const value = !this.state.isDone;
this.setState({ isDone: value });
const newValue = this.state.isDone;
console.log(newValue);
}
render() {
return (
<View>
<Button
title="Action"
// Add function with onPress
onPress={() => this.onAction}
/>
</View>
)
}
}
export default ToggleButton;

Incorrect integration into React props

I am trying to implement my first React-Redux app and got TypeError: Cannot read property 'map' of undefined from bundle.js. I guess it is associated with jokes array and its incorrect integration into my React jokeList component props:
import React from 'react';
import {connect} from 'react-redux';
class ListOfJokes extends React.Component {
constructor(props) {
super(props)
}
render() {
const {jokes} = this.props;
return (
<ul>
{jokes.map(joke => (<li>joke</li>))}
</ul>
)
}
}
const mapStateToProps = state => ({
jokes: state.jokes
})
export default connect(mapStateToProps, null)(ListOfJokes);
What is actually wrong with it?
Are you sure that store.jokes always contains something? If you fetch the data asynchronously, then on the first render store.jokes may be undefined. If that's the case then do:
const mapStateToProps = state => ({
jokes: state.jokes || []
})
Use a conditional loop to check jokes has or not. when sets the joke then it will mapping.
{jokes.length !== 0 ?
jokes.map(joke => (<li>joke</li>)) : (<li>no jokes</li>)
}

React Native. Getting value from ref attribute

I am trying to get value from a component but keep getting undefined refs.
Here is my code. From a function onClickSave(), I have tried to get this.refs to get a value of ref "input" in TextInputCell component but it's undefined. Is my code incorrect?
import React from 'react';
import { View, Text } from 'react-native';
import { Form, Section, TextInputCell } from 'react-native-forms';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import ActionBar3 from '../components/ActionBar3';
import * as profileActions from '../actions/profileActions';
const GLOBAL = require('../GlobalConstants');
class ProfileViewEdit extends React.Component {
constructor(props) {
super(props);
this.onClickSave.bind(this);
}
componentDidMount() {
console.log('componentDidMount');
}
onClickSave() {
console.log('aaabd');
console.log(this.refs);
}
render() {
const title = this.props.navigation.state.params.title;
let value = this.props.navigation.state.params.value;
return (
<View style={{ flex: 1, backgroundColor: '#EFEFF4' }}>
<ActionBar3
barTitle={title} navigation={this.props.navigation} onClickSave={this.onClickSave}
/>
<Section
title={title}
//helpText={'The helpText prop allows you to place text at the section bottom.'}
>
<TextInputCell
value={value}
ref="input"
/>
</Section>
</View>
);
}
}
const mapStateToProps = (state) => ({
stateProfile: state.profile
});
const mapDispatchToProps = (dispatch) => ({
actions: bindActionCreators(profileActions, dispatch)
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(ProfileViewEdit);
First thing that you are not handling events correctly. To use this in your events you need to bind this. Arrow functions bind it itself but you can bind manually to. More information is here.
You have to be careful about the meaning of this in JSX callbacks. In
JavaScript, class methods are not bound by default. If you forget to
bind this.handleClick and pass it to onClick, this will be undefined
when the function is actually called.
Second thing string refs are not suggested anymore. You should use functional ones. More info about that here.
Legacy API: String Refs
If you worked with React before, you might be familiar with an older
API where the ref attribute is a string, like "textInput", and the DOM
node is accessed as this.refs.textInput. We advise against it because
string refs have some issues, are considered legacy, and are likely to
be removed in one of the future releases. If you’re currently using
this.refs.textInput to access refs, we recommend the callback pattern
instead.
Example
<ActionBar3 barTitle={title} navigation={this.props.navigation} onClickSave={ () => this.onClickSave()} />
<TextInputCell value={value} ref={(ref) => { this.inputRef = ref; }} />

shall we use state or props for handling inputs in redux react?

I am confused with props or state to use here. If I use state in #connect I get error and does not work. when I use props it does not work with onchange handler to set new props. Please help how should I make input working with state or props. I am retrieving initial data from api.
import React, {PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import { asyncConnect } from 'redux-async-connect';
import {load, isLoaded} from 'redux/modules/overview';
#asyncConnect([{
promise: ({ store: { dispatch, getState }, params: { id }, }) => {
const promises = [];
if (!isLoaded(getState())) {
promises.push(dispatch(load(id)));
}
return Promise.all(promises);
}
}])
#connect(
state => ({
overview: state.overview.data
}),
dispatch => bindActionCreators({load}, dispatch))
export default class Overview extends React.Component {
changeinput1(e) {
this.props.overview.title = e.target.value;
// changing value does not work here
}
constructor (props) {
super();
this.state = {
overview: null,
}
}
render() {
return (
<div>
<label>Input 1</label>
<input type="text" className="form-control" id="title" name="title" maxlength="35" value={this.props.overview.title} onChange={this.changeinput1.bind(this)}/>
</div>
)
}
}
I also want to do validation and want to save input value on onBlur so I dont want to use form.
if you want change reducer's(here suppose to be 'overview') value, you should define an action then dispatch it, not change it directly, the state get from store is readonly in the component

Resources