0

I'm using React, Formik and Yup to make a form.

my form is not working. when i click on save button, my input is not saving the information I typed on the fields. it's saving blank information on the table.

and my cancel button is not clearing the fields. when i click on cancel button, nothing happens. need your help, guys! thanks.

import React, { Component } from 'react';
import Main from '../template/Main';
import axios from 'axios';
import { Helmet } from 'react-helmet';
import { confirmAlert } from 'react-confirm-alert';
import 'react-confirm-alert/src/react-confirm-alert.css';
import { BASE_URL } from './Url.json';
import { Formik, ErrorMessage, Form, Field } from 'formik';
import * as Yup from 'yup';

const initialState = {
  member: { avatar: '', name: '', email: '', project: '', devices: '', mainstack: '' },
  list: [],
};
export default class MemberCrud extends Component {
  constructor(props) {
    super(props);
    this.state = { ...initialState };
    //this.validateField = this.validateField.bind(this)
  }

  componentWillMount() {
    axios(BASE_URL).then((resp) => {
      this.setState({ list: resp.data });
    });
  }

  clear() {
    this.setState({ member: initialState.member });
  }

  save() {
    const member = this.state.member;
    const method = member.id ? 'put' : 'post';
    const url = member.id ? `${BASE_URL}/${member.id}` : BASE_URL;
    axios[method](url, member).then((resp) => {
      const list = this.getUpdatedList(resp.data);
      this.setState({ member: initialState.member, list });
    });
  }

  getUpdatedList(member) {
    const list = this.state.list.filter((u) => u.id !== member.id);
    list.unshift(member);
    return list;
  }

  updateField(event, field) {
    const member = this.state.member;
    member[field] = event.target.value;
    this.setState({ member });
  }

  renderInput(title, value, onChange, /*validateField,*/ placeholder, formik = {}) {
    return (
      <div className="col-12 col-md-4">
        <div className="form-groud">
          <label>{title}</label>
        </div>
        <div className="form-row">
          <Field
            type={placeholder}
            name={placeholder}
            id={placeholder}
            placeholder={placeholder}
            //   className={formik.errors[placeholder] && formik.touched[placeholder] ? "input-error" : null}
          />
          <ErrorMessage name={placeholder} component="span" className="error" />
        </div>
      </div>
    );
  }

  renderForm() {
    const formSchema = Yup.object().shape({
      avatar: Yup.string().required('Required'),
      name: Yup.string().required('Required'),
      email: Yup.string().required('Required'),
      project: Yup.string().required('Required'),
      devices: Yup.string().required('Required'),
      mainstack: Yup.string().required('Required'),
    });

    const initialState = {
      member: { avatar: '', name: '', email: '', project: '', devices: '', mainstack: '' },
      list: [],
    };

    return (
      <Formik
        initialValues={initialState.member}
        validationSchema={formSchema}
        onSubmit={(values) => {
          console.log(values);
        }}
      >
        {(formik) => {
          return (
            <Form>
              <div className="row" updateField={this.updateField}>
                {this.renderInput(
                  'Avatar',
                  this.state.member.avatar,
                  (e) => this.updateField(e, 'avatar'),
                  /*this.validateField,*/ 'avatar',
                )}
                {this.renderInput(
                  'Name',
                  this.state.member.name,
                  (e) => this.updateField(e, 'name'),
                  /*this.validateField,*/ 'name',
                )}
                {this.renderInput(
                  'Email',
                  this.state.member.email,
                  (e) => this.updateField(e, 'email'),
                  /*this.validateField,*/ 'email',
                )}
                {this.renderInput(
                  'Project',
                  this.state.member.project,
                  (e) => this.updateField(e, 'project'),
                  /*this.validateField,*/ 'project',
                )}
                {this.renderInput(
                  'Devices',
                  this.state.member.devices,
                  (e) => this.updateField(e, 'devices'),
                  /*this.validateField,*/ 'devices',
                )}
                {this.renderInput(
                  'MainStack',
                  this.state.member.mainstack,
                  (e) => this.updateField(e, 'mainstack'),
                  /*this.validateField,*/ 'mainstack',
                )}
              </div>

              <hr />
              <div className="row">
                <div className="col-12 d-flex justify-content-end">
                  <button
                    type="submit"
                    className={!(formik.dirty && formik.isValid) ? 'disabled-btn' : 'btn btn-primary'}
                    disabled={!(formik.dirty && formik.isValid)}
                    onClick={(e) => this.save(e)}
                  >
                    Save
                  </button>
                  <button
                    type="button"
                    className="btn btn-secondary ml-2"
                    onClick={(e) => this.clear(e)}
                    /*disabled={!(formik.dirty && formik.isValid)}*/
                  >
                    Cancel
                  </button>
                </div>
              </div>
            </Form>
          );
        }}
      </Formik>
    );
  }

  load(member) {
    this.setState({ member });
  }

  remove(member) {
    axios.delete(`${BASE_URL}/${member.id}`).then((resp) => {
      const list = this.state.list.filter((u) => u !== member);
      this.setState({ list });
    });
  }

  confirmRemove(member) {
    confirmAlert({
      message: 'Are you sure ?',
      buttons: [
        {
          label: 'Yes',
          onClick: () => this.remove(member),
        },
        {
          label: 'No',
        },
      ],
    });
  }

  renderTable() {
    return (
      <table className="table">
        <thead>
          <tr>
            <th>Profile Pictute</th>
            <th>Name</th>
            <th>Email</th>
            <th>Project</th>
            <th>Devices</th>
            <th>Main Stack</th>
            <th>Actions</th>
          </tr>
        </thead>
        <tbody>{this.renderRows()}</tbody>
      </table>
    );
  }

  renderRows() {
    return this.state.list.map((member) => {
      return (
        <tr key={member.id}>
          <td>
            <div className="avatar">
              <img src={member.avatar} alt={member.name} />
            </div>
          </td>
          <td>{member.name}</td>
          <td>{member.email}</td>
          <td>{member.project}</td>
          <td>{member.devices}</td>
          <td>{member.mainstack}</td>
          <td>
            <button className="btn btn-warning" onClick={() => this.load(member)}>
              <i className="fa fa-pencil"></i>
            </button>
            <button
              className="btn btn-danger ml-2"
              onClick={() => {
                this.confirmRemove(member);
              }}
            >
              <i className="fa fa-trash"></i>
            </button>
          </td>
        </tr>
      );
    });
  }

  render() {
    return (
      <Main>
        {this.renderForm()}
        {this.renderTable()}
        <Helmet>
          <title>Add Member</title>
        </Helmet>
      </Main>
    );
  }
}
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62

1 Answers1

1

You should use formik state, not ur component state. also for the reset field, you should use onSubmit={(e, { resetForm }) like this :

    <Formik
      initialValues={initialState.member}
      validationSchema={formSchema}
      onSubmit={(e, { resetForm }) => {
          //Your submit code
          ...
          //Then reset with this function
          resetForm({
            values: {
              ...e,
            },
          });
        }}
    >
    {({ handleChange, values, touched, errors }) => ( // <-- use this state
      <Form>
           // Your form code .jsx, you can seperate them aswell just pass state from above! 
      </Form>
     )}
    </Formik>

Formik Basic

b3hr4d
  • 4,012
  • 1
  • 11
  • 24
  • Thanks!! But I want to put formik and yup as I asked. Is it possible? for reset my form I'm using the code below and calling him on my cancel button. i'm using an json API. `clear() { this.setState({ member: initialState.member }); }` – user14801080 Dec 29 '20 at 20:29
  • Added more detail to answer, hope helps you. if you want to use `formik` as you asked you should build your own `formik` then :) – b3hr4d Dec 30 '20 at 07:19