rrboz
rrboz

Reputation: 15

How to declare an array with objects in the state ReactJS

I am wondering how to make new blank array with objects in the state and how to add element in it with setState.

I want the array so:

newhosts: [
      {
      activityState : "",
      platform: "",
      pushDate: "",
      name: "",
      ip: "",
      software: [{
        vulnerability: {
          link: "",
          desc: "",
          cvss: "",
          cve: ""
        },
        vulnerable: '',
        cpe: "",
        version: "",
        vendor: "",
        name: ""

      }]
      }
    ] 

Is it okay , so to declare the array in the state? How can I add later description oder items(for example description of the host and then description of all software elements on it). And how can I add for example two softwares to the same host?

 const namearray= this.state.filteredhosts.map(host=> {
        return (
           host.software.map((sub, subindex) => { 

          if(selectedOption==="name" || selectedOption==="vendor") {
            if(sub[selectedOption]=== writtenOption){


            newState.push(host.meta.name)
            newState.push(host.meta.ip)
            newState.push(sub.name) 
            newState.push(sub.vendor)
          }

         }
          else { 
            if(sub.vulnerable===true){
            newState.push(sub.vulnerability[selectedOption])}
            newState.push(host.meta.name)
            newState.push(host.meta.ip)  
          }
        })
        )
      })

Here I must replace this "newState.push" with your function, which save the data to the state.

Upvotes: 0

Views: 242

Answers (2)

Cat_Enthusiast
Cat_Enthusiast

Reputation: 15708

Having an array as a state-value is completely valid. Consider the sandbox I made for you: https://codesandbox.io/s/deeply-nested-inputs-mf70m

Your question gave me some inspiration and writing this out actually taught me a lot about handling nested inputs and how to update them.

This code will show you how to:

  • Create a new host object and the corresponding inputs for the user to fill.
  • Update a single host object, it's first layer such as fields activityState, platform, etc.
  • Update a single software object inside a host, including the inner vulnerability object and outer-fields such as vulnerable, cpe, etc.
  • Adding a new, additional software object to a host. And then updating those software objects.

Fill out the form with any combination of hosts and software, when you're finished hit the Click to Log Hosts button to print the finalized state.

The code:

import React from "react";
class App extends React.Component {
  state = {
    newhosts: [
      {
        activityState: "",
        platform: "",
        pushDate: "",
        name: "",
        ip: "",
        software: [
          {
            vulnerability: {
              link: "",
              desc: "",
              cvss: "",
              cve: ""
            },
            vulnerable: "",
            cpe: "",
            version: "",
            vendor: "",
            name: ""
          }
        ]
      }
    ]
  };

  handleOnChange = (event, hostindex, layer, softwareIndex) => {
    const { newhosts } = this.state;
    const copiedHosts = [...newhosts];
    const updatedHosts = copiedHosts.map((host, index) => {
      //find mathcing index to update that item
      if (hostindex === index) {
        //determine what layer of data we need to update
        if (layer === 1) {
          //we need to update activityState, platform etc...
          return {
            ...host,
            [event.target.name]: event.target.value
          };
        } else if (layer === 2) {
          //now we need to find the matching software item to update
          let updatedSoftware = copiedHosts[hostindex].software.map(
            (software, sIndex) => {
              if (softwareIndex === sIndex) {
                return {
                  ...software,
                  [event.target.name]: event.target.value
                };
              } else {
                return {
                  ...software
                };
              }
            }
          );
          return {
            ...host,
            software: updatedSoftware
          };
        } else if (layer === 3) {
          //now we need to find the matching software item to update
          let updatedSoftware = copiedHosts[hostindex].software.map(
            (software, sIndex) => {
              if (softwareIndex === sIndex) {
                return {
                  ...software,
                  vulnerability: {
                    ...software.vulnerability,
                    [event.target.name]: event.target.value
                  }
                };
              } else {
                return {
                  ...software
                };
              }
            }
          );
          return {
            ...host,
            software: updatedSoftware
          };
        }
      } else {
        //return all other hosts
        return host;
      }
    });
    this.setState({
      newhosts: updatedHosts
    });
  };

  createNewHostsForm = () => {
    const { newhosts } = this.state;

    return newhosts.map((host, hostIndex) => {
      return (
        <div>
          <h4>{`Host ${hostIndex + 1}`}</h4>
          {Object.entries(host).map(([key, value], lvl1Index) => {
            if (Array.isArray(value)) {
              const secondLayerInputs = [...value];
              return (
                <div>
                  <strong>software:</strong>
                  {secondLayerInputs.map((input, softwareIndex) => {
                    return Object.entries(input).map(([lvl2Key, lvl2Value]) => {
                      if (typeof lvl2Value === "string") {
                        return (
                          <div>
                            <label>{lvl2Key}</label>{" "}
                            <input
                              value={lvl2Value}
                              name={lvl2Key}
                              onChange={e =>
                                this.handleOnChange(
                                  e,
                                  hostIndex,
                                  2,
                                  softwareIndex
                                )
                              }
                            />
                          </div>
                        );
                      } else {
                        const thirdLayerInputs = { ...lvl2Value };
                        return Object.entries(thirdLayerInputs).map(
                          ([lvl3Key, lvl3Value]) => {
                            return (
                              <div>
                                <label>{lvl3Key}</label>{" "}
                                <input
                                  name={lvl3Key}
                                  value={lvl3Value}
                                  onChange={e =>
                                    this.handleOnChange(
                                      e,
                                      hostIndex,
                                      3,
                                      softwareIndex
                                    )
                                  }
                                />
                              </div>
                            );
                          }
                        );
                      }
                    });
                  })}
                  <button onClick={() => this.addSoftwareToHost(hostIndex)}>
                    Add Software
                  </button>
                </div>
              );
            } else {
              return (
                <div>
                  <label>{key}</label>{" "}
                  <input
                    value={value}
                    onChange={e => this.handleOnChange(e, hostIndex, 1)}
                    name={key}
                  />
                </div>
              );
            }
          })}
        </div>
      );
    });
  };

  addNewHost = () => {
    const newHostObj = {
      activityState: "",
      platform: "",
      pushDate: "",
      name: "",
      ip: "",
      software: [
        {
          vulnerability: {
            link: "",
            desc: "",
            cvss: "",
            cve: ""
          },
          vulnerable: "",
          cpe: "",
          version: "",
          vendor: "",
          name: ""
        }
      ]
    };
    this.setState({
      newhosts: [...this.state.newhosts, newHostObj]
    });
  };

  addSoftwareToHost = hostIndex => {
    const { newhosts } = this.state;
    const copiedHosts = [...newhosts];
    const newSoftwareObj = {
      vulnerability: {
        link: "",
        desc: "",
        cvss: "",
        cve: ""
      },
      vulnerable: "",
      cpe: "",
      version: "",
      vendor: "",
      name: ""
    };

    const updatedHosts = copiedHosts.map((host, index) => {
      if (hostIndex === index) {
        return {
          ...host,
          software: [...host.software, newSoftwareObj]
        };
      } else {
        return {
          ...host
        };
      }
    });

    this.setState({
      newhosts: updatedHosts
    });
  };

  handleSubmit = () => {
    console.log(this.state.newhosts);
  };

  render() {
    return (
      <div>
        {this.createNewHostsForm()}
        <div style={{ margin: "25px 0px" }}>
          {" "}
          <button onClick={this.addNewHost}>Add Host</button>
        </div>
        <button onClick={this.handleSubmit}>Click to Log Hosts</button>
      </div>
    );
  }
}

Upvotes: 0

bkm412
bkm412

Reputation: 1057

I think you have this data

state = {
   newhosts : [{hostdata1}, {hostdata2}]
}

add host description

function addHostDescription = (selectHostIp) => {
    const copyState = [...this.state.newhosts];
    const hostIndex = copyState.findIndex(host => host.ip === selectHostIp);
    copyState[hostIndex] = {...copyState[hostIndex], description : 'description content'};
    this.setState({
        newhosts : copyState
    })
}

add new software

function addNewSoftware = (selectHostIp, newSoftware) => {
    const copyState = [...this.state.newhosts];
    const hostIndex = copyState.findIndex(host => host.ip === selectHostIp);
    copyState[hostIndex].software.push(newSoftware);
    this.setState({
        newhosts : copyState
    })
}

add new host

function addNewHost = (newHost) => {
    const copyState = [...this.state.newhosts];
    copyState.push(newHost);
    this.setState({
        newhosts : copyState
    })
}

Upvotes: 2

Related Questions