React Nested Array

女生的网名这么多〃 提交于 2020-02-07 05:31:30

问题


I need to be able to combine this into one function. There are 2 separate arrays...

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

and...

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

Basically, this is because I have a button which concatenates the 2 functions and it has to be outside the row class (MDBRow) so the UI doesn't break.

<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>

This is the handleAddTelephone function...

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

};

and the Constructor looks like this...

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

Can I nest one array inside the other? I'm not sure how to do this so any advice appreciated. Thanks.

Edit: These are the 2 telephone functions which need to be 1 function... I have updated with new nested array for each

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)
    }
    );
};

My constructor now looks like this...

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

回答1:


Although I still don't quite understand how your UI "breaks" (video won't load for me), I hope I can help. Basically the short answer about trying to map two arrays singly is that you can't (well, shouldn't), but with some assumptions about the two array's length always being equal and the order is the same between the two, then you can map over the first array and use the passed index from the map function to access the second.

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

I think the better solution is to keep only a single array in state to map over in the first place.

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

If you also really want only a single change handler (I recommend they be separate), you can adopt a redux action/reducer type handler that accepts an object as a parameter that has all the data you need to update an array entry (index, update type, value). Here's a pretty clean example, but requires a bit of "action" setup when called:

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}`}
/>

Below I've created a few working sandbox demos:

  • Dual telephone data arrays, single change ("action/reducer") handler, separate add/remove functions, single map pass using index accessor to second array:
  • Single telephone data array, single change handler, separate add/remove, single map pass:
  • Use react useReducer, single array, reducer handles add/remove/update, single map pass:

I've included code documentation but if anything is unclear please let me know and I can clean up these demos.




回答2:


Yes, absolutely, something along:

telephone: {
  list: [1,2,3],
  type: [“foo”, “bar”, “baz”]
}


来源:https://stackoverflow.com/questions/56807902/react-nested-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!