Реагировать на вложенный массив - PullRequest
0 голосов
/ 28 июня 2019

Мне нужно объединить это в одну функцию. Есть 2 отдельных массива ...

{this.state.telephoneType.map((telephoneType, ttidx) => ())}

и ...

{this.state.telephone.map((telephone, tidx) => ())}

По сути, это потому, что у меня есть кнопка, которая объединяет 2 функции, и она должна быть вне класса строк (MDBRow), чтобы пользовательский интерфейс не прерывался.

<MDBRow className="grey-text no-gutters my-2">

    {this.state.telephoneType.map((telephoneType, ttidx) => (

        <MDBCol md="4" className="mr-2">
            <select
                key={ttidx}
                defaultValue={telephoneType.name}
                onChange={this.handleTelephoneTypeChange(ttidx)}
                className="browser-default custom-select">
                <option value="Mobile">Mobile</option>
                <option value="Landline">Landline</option>
                <option value="Work">Work</option>
            </select>
        </MDBCol>
    ))}

    {this.state.telephone.map((telephone, tidx) => (

        <MDBCol md="7" className="d-flex align-items-center">
            <input
                value={telephone.name}
                onChange={this.handleTelephoneChange(tidx)}
                placeholder={`Telephone No. #${tidx + 1}`}
                className="form-control"
            />
            <MDBIcon icon="minus-circle"
                className="mr-0 ml-2 red-text"
                onClick={this.handleRemoveTelephone(tidx)} />
        </MDBCol>

    ))}

</MDBRow>

<div className="btn-add" onClick={this.handleAddTelephone}>
    <MDBIcon className="mr-1" icon="plus-square" />
        Add Telephone
</div>

Это функция handleAddTelephone ...

handleAddTelephone = () => {
    this.setState({
        telephone: this.state.telephone.concat([{ name: "" }]),
        telephoneType: this.state.telephoneType.concat([{ name: "" }])
    });

};

и конструктор выглядит так ...

class InstallerAdd extends React.Component {
    constructor() {
        super();
        this.state = {
            role: "Installer",
            name: "",
            telephoneType: [{ name: "" }],
            telephone: [{ name: "" }],
            tidx: "",
            emailType: [{ email: "" }],
            email: [{ email: "" }],
            eidx: "",
            notes: ""
        };
    }
}

Могу ли я вложить один массив в другой? Я не уверен, как это сделать, поэтому любые советы приветствуются. Спасибо.

Edit: Это две функции телефона, которые должны быть одной функцией ... Я обновил новый вложенный массив для каждого

handleTelephoneChange = tidx => evt => {
    const newTelephone = this.state.telephone.type.map((telephone, tsidx) => {

        if (tidx !== tsidx) return telephone;
        return { ...telephone, name: evt.target.value };
    });
    this.setState({ telephone: newTelephone }, () => {
        // get state on callback
        console.log(this.state.telephone.number[tidx].name)
    }
    );
};

handleTelephoneTypeChange = ttidx => evt => {
    const newTelephoneType = this.state.telephone.number.map((telephoneType, ttsidx) => {
        if (ttidx !== ttsidx) return telephoneType;
        return { ...telephoneType, name: evt.target.value };
    });
    this.setState({ telephoneType: newTelephoneType }, () => {
        // get state on callback
        console.log(this.state.telephone.type[ttidx].name)
    }
    );
};

Мой конструктор теперь выглядит так ...

class InstallerAdd extends React.Component {
    constructor() {
        super();
        this.state = {
            role: "Installer",
            name: "",
            telephone: {
                type: [{ name: "" }],
                number: [{ name: "" }]
              },
            tidx: "",
            emailType: [{ email: "" }],
            email: [{ email: "" }],
            eidx: "",
            notes: ""
        };
    }

Ответы [ 2 ]

0 голосов
/ 21 июля 2019

Хотя я все еще не совсем понимаю, как ваш пользовательский интерфейс «ломается» (видео не загружается для меня), я надеюсь, что смогу помочь.По сути, короткий ответ о попытке сопоставить два массива по отдельности заключается в том, что вы не можете (ну, не должно ), но с некоторыми предположениями о том, что длина двух массивов всегда равна, вы можете отобразить первый массиви используйте переданный index из функции map для доступа ко второму.

arrayA.map((itemFromA, index) => {
  // do stuff with item from A
  const itemFromB = arrayB[index];
  // do stuff with item from B
});

Я думаю, что лучшее решение состоит в том, чтобы сохранить только один массив в состоянии для отображения в первую очередь.

state = {
  telephones: [], // { type: string, number: string }[]
}
...
state.telephones.map(({ type, number }, index) => {
  // do stuff with telephone type
  ...
  // do stuff with telephone number
});

Если вы также действительно хотите только один обработчик изменений (я рекомендую, чтобы они были разделены), вы можете принять обработчик типа действия редукса / редуктора, который принимает объектв качестве параметра, который содержит все данные, необходимые для обновления записи массива (индекс, тип обновления, значение).Вот довольно чистый пример, но требует немного «экшн» настройки при вызове:

changeHandler = (index, type) => e => {
  const newTelephoneData = [...this.state.telephones];
  newTelephoneData[index][type] = e.target.value;
  this.setState({ telephones: newTelephoneData });
}

<select
  value={type}
  onChange={this.telephoneChangeHandler(index, "type")}
>
  // options
</select>

...

<input
  value={number}
  onChange={this.telephoneChangeHandler(index, "number")}
  placeholder={`Telephone No. #${index + 1}`}
/>

Ниже я создал несколько рабочих демонстраций песочницы:

  • Двойные телефонные данныемассивы, обработчик одиночного изменения («действие / редуктор»), отдельные функции добавления / удаления, одиночный проход карты с использованием индексного метода доступа ко второму массиву: Edit nested-dual-array-update
  • один телефонный массив данных, одинизменить обработчик, отдельно добавить / удалить, один проход карты: Edit nested-single-array-update
  • Использовать реакцию useReducer, один массив, редуктор обрабатывает добавление / удаление / обновление, один проход карты: Edit nested-single-array-update-hooks

Я включил документацию по коду, но если что-то неясно, пожалуйста, дайте мне знать, и я могу очистить эти демонстрации.

0 голосов
/ 28 июня 2019

Да, конечно, что-то не так:

telephone: {
  list: [1,2,3],
  type: [“foo”, “bar”, “baz”]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...