Как спроектировать State для нескольких объектов с использованием response-redux? - PullRequest
0 голосов
/ 09 апреля 2020

Мне нужно создать несколько объектов медицины здесь. Я просто хочу изменить состояние в массив объектов. Как это сделать эффективно? Кроме того, вы хотите реализовать управляемый компонент для нескольких объектов медицины.

Form Design

Вот мой компонент для одного объекта медицины:

export class MedicineForm extends Component {
    state = {
        medicine_name: "",
        details: ""
    }

    static propTypes = {
        postMedicine: PropTypes.func.isRequired
    }

    onChange = e => {
        this.setState({
          [e.target.name]: e.target.value
        })
    }

    onSubmit = e => {
        e.preventDefault()
        const { medicine_name, details } = this.state
        const medicine = { medicine_name, details }
        this.props.postMedicine(medicine)
        // Following code works as desired.  Need to change state in this JSON Array of objects.

        // this.props.postMedicine([
        //  {
        //      "id": 14,
        //      "medicine_name": "many5",
        //      "details": "sdknas"
        //  },
        //  {
        //      "id": 15,
        //      "medicine_name": "many6",
        //      "details": "sdknas"
        //  }
        // ])
    }

    render() {
        const { medicine_name, details } = this.state

        return (
          <Fragment>
            <h1>Add Medicine</h1>
            <form className="card card-body" onSubmit={this.onSubmit}>
              <div className="form-row">
                <div className="form-group col-md-3">
                  <label htmlFor="medicine_name">Medicine Name</label>
                  <input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={medicine_name} onChange={this.onChange} />
                </div>
                <div className="form-group col-md-3">
                  <label htmlFor="details">Details</label>
                  <input type="text" className="form-control" name="details" id="details" placeholder="Details" value={details} onChange={this.onChange} />
                </div>
                <div className="form-group mx-auto mt-3">
                  <button type="submit" className="btn btn-primary btn-lg">
                    Submit
                  </button>
                </div>
              </div>
            </form>
          </Fragment>
        )
    }
}

В действиях я добавил следующий постМедицинский метод:

export const postMedicine = (medicine) => dispatch => {
    axios.post('./api/medicine/', medicine)
        .then(res => {
            dispatch({
                type: POST_MEDICINE,
                payload: res.data
            })
        })
        .catch(err => console.log(err))
}

Ответы [ 3 ]

1 голос
/ 09 апреля 2020
//this is one row, add multiple rows as needed        
state = {
    medicines: [{medicine_name: "",
            details: ""
    }]
    }
    //other code

    onChange = (e, i) => {
        const newMedicines = this.state.medicines;
        newMedicines[i] = {[e.target.name]: e.target.value, ...newMedicines[i]}
        this.setState({medicines: newMedicines})
    }

    onSubmit = e => {
        e.preventDefault()
        const { medicine_name, details } = this.state
        const medicine = { medicine_name, details }
        this.props.postMedicine(medicine)
        // Following code works as desired.  Need to change state in this JSON Array of objects.

        // this.props.postMedicine(this.state.medicines)
    }


    <form className="card card-body" onSubmit={this.onSubmit}>
                  {this.state.medicines.map((m, i) => (<div className="form-row">
                    <div className="form-group col-md-3">
                      <label htmlFor="medicine_name">Medicine Name</label>
                      <input type="text" className="form-control" name="medicine_name" id="medicine_name" placeholder="Medicine Name" value={m.medicine_name} onChange={(e) => this.onChange(e, i)} />
                    </div>
                    <div className="form-group col-md-3">
                      <label htmlFor="details">Details</label>
                      <input type="text" className="form-control" name="details" id="details" placeholder="Details" value={m.details} onChange={(e) => this.onChange(e, i)} />
                    </div>
                    <div className="form-group mx-auto mt-3">
                      <button type="submit" className="btn btn-primary btn-lg">
                        Submit
                      </button>
                    </div>
                  </div>))}
                </form>
0 голосов
/ 09 апреля 2020

Компонент формы имеет два параметра (он же реквизит). первый - item , который определяет, сколько формы вам нужно. 1 форма означает, что у вас есть группа из двух входов [имя_медицины, подробности] 2 = 4 входа (2 группы) ... et c

, а второй реквизит - это функция с именем formHandler . при получении данных от дочернего элемента

export class MedicineForm extends Component {
  state = {
    medicine: [],
  };

  static propTypes = {
    postMedicine: PropTypes.func.isRequired,
  };

  formHandler = (value) => {
    this.setState({ medicine: value });
  };

  onSubmit = (e) => {
    e.preventDefault();
    this.props.postMedicine(this.medicine);
  };

  render() {
    return (
      <>
        <h1>Add Medicine</h1>
        {JSON.stringify(this.state.medicine)}
        <form className="card card-body" onSubmit={this.onSubmit}>
          <Form item="4" formHandler={this.formHandler} />
          <div className="form-group mx-auto mt-3">
            <button type="submit" className="btn btn-primary btn-lg">
              Submit
            </button>
          </div>
        </form>
      </>
    );
  }
}

Компонент формы

class Form extends Component {
  constructor(props) {
    super(props);
  }
  state = {
    medicine: [...Array(+this.props.item)].map((_, idx) => ({
      id: idx + 1,
      medicine_name: "",
      details: "",
    })),
  };
  static propTypes = {
    item: PropTypes.string,
    formHandler: PropTypes.func,
  };

  onChange = ({ target: { id, name, value } }) => {
    this.setState((prevState) => {
      const medicine = prevState.medicine.map((item) =>
        item.id === Number(id) ? { ...item, [name]: value } : item
      );
      this.props.formHandler(
        medicine.filter((item) => item["medicine_name"] || item["details"])
      );
      return {
        medicine,
      };
    });
  };

  render() {
    return (
      <div className="form-row">
        {this.state.medicine.map((item, id) => (
          <div key={item.id}>
            <div className="form-group col-md-3">
              <label htmlFor="medicine_name">Medicine Name</label>
              <input
                type="text"
                className="form-control"
                name="medicine_name"
                id={item.id}
                value={item.medicine_name}
                placeholder="Medicine Name"
                onChange={this.onChange}
              />
            </div>
            <div className="form-group col-md-3">
              <label htmlFor="details">Details</label>
              <input
                type="text"
                className="form-control"
                name="details"
                id={item.id}
                value={item.details}
                placeholder="Details"
                onChange={this.onChange}
              />
            </div>
          </div>
        ))}
      </div>
    );
  }
}

проверяется, имеет ли объект какое-либо значение, а затем данные подъема. Вы можете изменить логи c опционально

medicine.filter((item) => item["medicine_name"] || item["details"])
0 голосов
/ 09 апреля 2020

Вы можете сделать что-то подобное в хранилище резервов:

[
  { id: 1, medicineName: '', details: '' },
  { id: 2, medicineName: '', details: '' },
  ...
]

И чтобы ваши входные поля контролировались, просто обрабатывайте состояние в компоненте.

...