Реакция Js Обновление значения внутри массива с помощью onChange для дочернего компонента - PullRequest
2 голосов
/ 01 июня 2019

У меня есть список с открытие_часов, который я отображаю в моей функции рендеринга. Я сопоставляю их с дочерним компонентом. Я хочу изменить значение каждого объекта в моем родительском состоянии при изменении состояния дочернего компонента. Единственная проблема заключается в том, что мои значения не меняются ни в дочернем компоненте, ни в родительском состоянии. Я передал метод onChange каждому дочернему компоненту, но проблема заключается в моей функции onChange в родительском состоянии.

Я попытался передать onChange своему дочернему компоненту и обновить состояние с помощью [e.target.name]: e.target.value. Но это не сработало. Поэтому я попытался скопировать arrayList и обновить состояние, основываясь на индексе сопоставленного arrayList. Это тоже не сработало.

    handleOnChange =  (index) => {
        let newData = [...this.state.opening_hours];
        this.setState(
            newData.map((barbershop, j) => {
                if (j === index) {
                    return barbershop;
                    console.log(barbershop)
                }
            return {
                newData,
            };
        }));
        console.log(newData)
    };

    render() {
        return (
            <>
                <div className="container mb-2">
                    <h4>Opening hours </h4>
                    <Form>
                        {this.state.opening_hours.map((barbershop, index) => (
                            <Day
                                key={barbershop.id}
                                day={barbershop.day}
                                open_time={barbershop.open_time}
                                close_time={barbershop.close_time}
                                index = {index}
                                onChange={() => this.handleOnChange(index)}/>
                        ))}
                    </Form>


                    <Button onClick={this.handleSubmit} variant="primary" type="submit">
                        Update opening hours
                    </Button>
                </div>
            </>
        );
    }
}

Мой дочерний компонент выглядит так

class Day extends Component {

    constructor(props) {
        super(props);
        this.state = {
            day: this.props.day,
            open_time: this.props.open_time,
            close_time: this.props.close_time,
        };
        console.log(this.state)
    }

    handleChange = () => {
        this.props.onChange(this.props.index)
    }

    render() {
        return (
                <Form.Group as={Row}>
                <Form.Label column sm="3">
                    {ENUM[this.state.day]}
                </Form.Label>
                <Col sm="3">
                    <Form.Control
                        name="open_time"
                        value={this.state.open_time}
                        onChange={this.handleChange}
                        type="time"
                        min="08:00"
                        max="24:00"/>
                </Col>
                <Col sm="3">
                    <Form.Control
                        name="close_time"
                        value={this.state.close_time}
                        onChange={this.handleChange}
                        type="time"
                        min="08:00"
                        max="24:00"/>
                </Col>
            </Form.Group>
        );
    }
}

EDIT:

enter image description here

Ответы [ 2 ]

2 голосов
/ 01 июня 2019

Итак, я провел некоторое расследование, и я считаю, что проблема в том, что вы не возвращаете данные потребителю.

Вот то, что я думаю, решение:

import React, { Component, useState, useEffect } from "react";

class UI extends Component {
  handleOnChange = ({ index, ...newHours }) => {
    // update array item
    const opening_hours = this.state.opening_hours.map((item, i) => {
      const newData = i === index ? newHours : {};

      return {
        ...item,
        ...newData
      };
    });

    // update item in opening_hours => state
    this.setState({ opening_hours });
  };

  render() {
    return (
      <div className="container mb-2">
        <h4>Opening hours</h4>

        <Form>
          {this.state.opening_hours.map(({ id, ...barbershop }, index) => (
            <Day
              key={id}
              {...barbershop}
              {...{ index }}
              onChange={this.handleOnChange}
            />
          ))}
        </Form>

        <Button onClick={this.handleSubmit} variant="primary" type="submit">
          Update opening hours
        </Button>
      </div>
    );
  }
}

const Day = ({ day, onChange, index, ...props }) => {
  const [open_time, setOpenTime] = useState(props.open_time);
  const [close_time, setCloseTime] = useState(props.close_time);

  useEffect(() => {
    onChange({ index, open_time, close_time });
  }, [open_time, close_time, onChange, index]);

  const sharedProps = {
    type: "time",
    min: "08:00",
    max: "24:00"
  };

  return (
    <Form.Group as={Row}>
      <Form.Label column sm="3">
        {ENUM[day]}
      </Form.Label>

      <Col sm="3">
        <Form.Control
          {...sharedProps}
          name="open_time"
          value={open_time}
          onChange={({ target }) => setOpenTime(target.value)}
        />
      </Col>

      <Col sm="3">
        <Form.Control
          {...sharedProps}
          name="close_time"
          value={close_time}
          onChange={({ target }) => setCloseTime(target.value)}
        />
      </Col>
    </Form.Group>
  );
};
1 голос
/ 01 июня 2019

Вы передаете функцию, которая вызывает this.handleChange(index), но вы действительно должны передать этот метод в качестве опоры вашему <Day /> компоненту и вызвать его там. Вы уже передаете index (хотя я бы использовал barbershop.id вместо)

Итак, в вашем родительском компоненте я бы сделал это вместо:

<Day 
  key={barbershop.id}
  day={barbershop.day}
  open_time={barbershop.open_time}
  close_time={barbershop.close_time}
  index = {barbershop.id}
  handleChange={this.handleOnChange}
/>

Тогда в вашем методе this.handleChange в родительском компоненте, если вы просто пытаетесь получить this.state.opening_hours для конкретной парикмахерской, я бы сделал что-то вроде этого:

handleChange = (id) => {
  this.setState(() => ({
    opening_hours: this.state.opening_hours.filter((barbershop) => { 
      return barbershop.id === id;
    })
  }))
}
...