Цель
Настройка динамической формы, контролируемой пользователем, с использованиемact-redux и revalidate для запуска проверок в моей форме.
Проблема:
Поскольку моя форма является динамической, мне нужно выполнить динамические проверки.Для этого мои данные формы должны быть переданы как компонент моего компонента, который можно использовать в качестве второго аргумента в функции проверки от revalidate
Мой подход
Для этогоЯ жду, пока компонент будет смонтирован, создаю форму, передаю ее в Redx, а затем сопоставлю состояние с реквизитом.Поскольку пользователь добавляет больше строк, я буду обновлять состояние, а затем компонент будет визуализироваться.Я буду использовать shouldComponentUpdate (), чтобы избежать циклов рендеринга.
Ошибка
Моя ошибка связана с отправкой.Когда я пытаюсь запустить диспетчеризацию (которая передаст форму в редукс), я получаю ошибку Dispatch is not a function
.
Я не чувствую себя комфортно с connect()
, так как я должен обернуть его как реверсом, так иfirebase.Этот синтаксис действительно смущает меня.
Вопрос
Я считаю, что проблема с тем, как я экспортирую компонент, где я использую HOC, как withFirebase, Redux и Connect.Где-то по пути я теряю интерес к соединению.Может кто-то пролить свет на то, что я делаю неправильно?
Компонент
import React, { Component } from "react";
import { reduxForm, Field } from "redux-form";
import { Container, Form, Col, Button } from "react-bootstrap";
import MaterialIcon from '../../material-icon/materialIcon';
import { withFirestore } from "react-redux-firebase";
import { connect } from "react-redux";
import TextInput from "../../forms/textInput";
import { combineValidators, isRequired } from "revalidate";
import { setupStudentForm } from '../../../store/actions/students';
const validate = (values, ownprops) => {
// Will be passing in validation rules, once form is apssed in with props via mapStateToProps.
}
export class CreateStudentsForm extends Component {
// Using constrcutor so componentDidMount() can render() cann access variables
constructor(props) {
super(props);
this.state = {
rows: 2,
}
this.formArray = [];
this.form = null;
}
componentDidMount() {
// Once component is rendered, setup form and send to redux
for (let i = 1; i !== this.state.rows + 1; i++) {
let firstNameField = {
fieldName: `firstName${i}`,
label: 'First Name',
required: true,
type: "text",
}
let lastNameField = {
fieldName: `lastName${i}`,
label: 'Last Name',
required: true,
type: "text",
}
this.formArray.push([firstNameField, lastNameField]);
}
this.props.setupStudentFormHandler(this.formArray);
}
// Ensure we do not get stuck in render loop
shouldComponentUpdate(nextProps, nextState){
if(nextProps !== this.props){
return true
} else {
return false
}
}
render() {
// Allows user to add another row
const addRow = () => {
this.setState({
rows: this.state.rows + 1
})
}
// Map through form array and create template
if (this.formArray) {
let form = this.formArray.map((field, index) => {
return (
<Form.Row key={index} className="animated fadeIn">
<Col xs={5}>
<Form.Group className="mb-0 noValidate">
<Field
label={field[0].label}
attempt={this.props.attempt}
name={field[0].fieldName}
type={field[0].type}
component={TextInput}
/>
</Form.Group>
</Col>
<Col xs={5}>
<Form.Group className="mb-0 noValidate">
<Field
label={field[1].label}
attempt={this.props.attempt}
name={field[1].fieldName}
type={field[1].type}
component={TextInput}
/>
</Form.Group>
</Col>
<Col xs={2}>
<MaterialIcon icon="delete" className="mt-4" />
</Col>
</Form.Row>
)
})
}
return (
<Container>
{this.form}
<Button variant="outline-success" onClick={addRow}>Add Another Student</Button>
</Container>
)
}
}
const mapStateToProps = state => {
return {
// Get access to student state which will have form
studentForm: state.students
};
};
const mapDispatchToProps = dispatch => {
return {
//Send formArray to redux
setupStudentFormHandler: (form) => dispatch(setupStudentForm(form))
};
};
export default withFirestore(
reduxForm({
form: "createStudents", validate
})(connect(
mapDispatchToProps,
mapStateToProps
)(CreateStudentsForm)
)
);