I am having a problem while using ref
via connect and redux-form together.
The structure of component is such that the ChildComponent has Forms and I am using
class EditEvent extends Component {
constructor (props) {
super(props);
this.handleStartDateChange = this.handleStartDateChange.bind(this);
this.handleEndDataChange = this.handleEndDataChange.bind(this);
this.state = {loading: false};
}
componentDidMount(){
this.props.fetchEvent(this.props.session,true);
this.props.fetchScheduleDates(this.props.session);
}
submitSettings(){
this.props.form.submit();
}
handleStartDateChange(date) {
this.props.updateUnsavedChanges();
this.props.dateRangeUpdate({startDate:date,endDate:date,allDate:{}});
}
handleEndDataChange(date) {
this.props.updateUnsavedChanges();
this.props.dateRangeUpdate({startDate:this.props.scheduledates.startDate,endDate:date,allDate:{}});
}
renderBlockList(startDate,endDate,allDate){
/*if(isEmpty(allDate)){
return 'Please select date duration first.';
}*/
var arr = [];
var day = {};
var n = endDate.diff(startDate,'days')+1;
for (var i=1; i <= n; i++ ) {
if(i !== 1){
day = moment(day).add(1,'days');
} else {
day = startDate;
}
var activeDate = _.find(allDate, {scheduledate:moment(day).format('YYYY-MM-DD')});
arr.push(<DateBlock key={i} day={day} activeDate={activeDate}/>);
}
return arr;
}
handleEventName(){
this.props.updateUnsavedChanges();
}
handleEventDesc(){
this.props.updateUnsavedChanges();
}
onFormSubmit(values){
debugger;
if (this.props.selectedFeatures.length === 0) {
this.props.showError('Select at least one feature!');
} else if (values.eventname === '') {
this.props.showError('Please enter a name');
} else {
this.props.submitSettingsHandler(values);
}
}
render(){
var eventStartDate = moment();
var eventEndDate = moment().add(6,'days');
var isDisabled = false;
var allDate = [];
if(this.props.scheduledates.startDate !== undefined){
eventStartDate = this.props.scheduledates.startDate;
eventEndDate = this.props.scheduledates.endDate;
allDate = this.props.allDate;
}
if(this.props.scheduledates.isEditable !== undefined){
isDisabled = true;
}
var {handleSubmit, pristine, submitting, invalid} = this.props;
return(
<form onSubmit={handleSubmit(this.onFormSubmit.bind(this))} encType="multipart/form-data">
<div className="general-tab-warp">
<Field
name="eventname"
label="Event name"
placeholder="E.g google I/O 2017"
type="text"
component={this.renderFieldText}
bsClass="row"
formdiv="false"
labelposition={LABEL_POSITION_TOP}
onChange={this.handleEventName.bind(this)}
/>
<Field
name="eventdesc"
label="Event Description"
placeholder="Enter event description"
type="text"
component={this.renderFieldTextarea}
bsClass="row"
formdiv="false"
labelposition={LABEL_POSITION_TOP}
onChange={this.handleEventDesc.bind(this)}
/>
<div className="form-group row">
<label className="control-label-top col-sm-12">Duration*</label>
<div className="col-sm-12">
<Row>
<Col md={6} style={{width:'48%'}}>
<DatePicker
selected = {eventStartDate}
className = "form-control"
dateFormat = "DD/MM/YYYY"
onChange = {this.handleStartDateChange}
name = "startdate"
selectsStart
startDate = {eventStartDate}
endDate = {eventEndDate}
minDate = {moment().add(1,'days')}
disabled={isDisabled}
/>
</Col>
<Col md={1} style={{padding:'0px',marginTop:'6px', width:'4%'}}>➔</Col>
<Col md={6} style={{width:'48%'}}>
<DatePicker
selected = {eventEndDate}
className = "form-control"
dateFormat = "DD/MM/YYYY"
onChange = {this.handleEndDataChange}
name = "enddate"
minDate = {eventStartDate}
maxDate = {moment(eventStartDate).add(6, "days")}
selectsEnd
startDate = {eventStartDate}
endDate = {eventEndDate}
disabled={isDisabled}
/>
</Col>
</Row>
<div className="duration-info">
* You can't update the date after publishing the app.
</div>
</div>
</div>
<div className="form-group row">
<label className="control-label-top col-sm-12">Days</label>
<div className="col-sm-12">
<ul className="event-days">
{this.renderBlockList(eventStartDate,eventEndDate,allDate)}
</ul>
</div>
</div>
<div className="form-group row">
<label className="control-label-top col-sm-12">Event Privacy</label>
<div className="col-md-12">
<FormGroup>
<Radio name="event_privacy" inline>
Public
</Radio>{' '}
<Radio name="event_privacy" inline>
Private
</Radio>
</FormGroup>
</div>
</div>
</form>
);
}
}
function mapStateToProps(state){
return{
features: state.features,
session: state.session,
initialValues: state.eventData[0],
scheduledates:state.scheduledates,
allDate:state.updateScheduleDates,
selectedFeatures: state.selectedFeatures
};
}
function validate(values) {
var errors = {};
if (values['eventname'] === '') {
errors['eventname'] = 'Event name is required';
}
return errors;
}
export default connect(mapStateToProps,{fetchEvent,updateUnsavedChanges,fetchScheduleDates,dateRangeUpdate,patchEventDetails,showError,showSuccess},null,{withRef:true})(reduxForm({
validate,
form:'EditEventForm',
enableReinitialize: true,
keepDirtyOnReinitialize: true
})(EditEvent));
The component has a function
submitSettings(){
this.props.form.submit();
}
I want to call submitSettings from Parent component, in which I am using ref, see below
constructor(props){
super(props);
this.editEventRef = React.createRef();
}
onSaveClick(){
this.editEventRef.current.submitSettings();
}
render(){
return(
<EditEvent ref={this.editEventRef}/>
)
}
When onSaveClick is called I always get the following error
Uncaught TypeError: this.editEventRef.current.submitSettings is not a function
The error goes and the function works fine the moment I change the following line and remove the use of reduxForm()
in connect()
export default
connect(mapStateToProps,
{fetchEventDetails}
,null,{withRef:true})(EditEvent);
Can anyone please guide me to solve this? Am I missing something?
Thanks for Help.
Update These are the npm versions of packages I am using, if that helps.
"react": "^16.7.0" "react-dom": "^16.7.0", "react-redux": "^5.1.1", "redux-form": "^6.7.0",
React Redux recently released version 7.1, which includes long awaited support for React Hooks. This means that you can now ditch the connect higher-order component and use Redux with Hooks in your function components.
You can keep them in your app's redux store in any persistence like web storage.
If you're only using Redux to avoid passing down props, you can replace it with Context API. Context is great for sharing trivial pieces of state between components. Redux is much more powerful and provides a set of handy features that Context doesn't have.
The connect() function connects a React component to a Redux store. It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.
OK, so after spending so much time I found the solution this is true for "react": "^16.7.0" and "redux-form": "^8.1.0" which is latest right now.
When you are using connect() reduxForm()
the way I am doing in the question, you need to use
this.editEventRef.current.wrappedInstance.submitSettings();
So whenever there is reduxForm in child component you need to use .current.wrappedInstance to access the callback, else use .current only.
You need to use {forwardRef:true}
as option in connect()
I didn't find it documented anywhere though but above works.
Hope it helps someone looking for similar answer.
Cheers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With