Home > Software engineering >  Passing data component to component in React JS
Passing data component to component in React JS

Time:07-16

I'm super new to React JS and developing small employee data view and filtering app. Below is my working code.

EmployeeList.js

function EmployeeList(props) {
    const [mainData, setMainData] = useState(props.data);
    const [selectedDept, setSelectedDept] = useState(null);
    const [selectedLocation, setSelectedLocation] = useState(null);

    var departmentCodes = [...new Set(props.data.map(item => item.department))];
    departmentCodes.push("-SELECT-");
    departmentCodes.sort();

    var locationCodes = [...new Set(props.data.map(item => item.factoryLocation))];
    locationCodes.push("-SELECT-");
    locationCodes.sort();

    const handleComboDepartment = (event) => {
        setSelectedDept(event);
        filterAgain("Department", event);
    };

    const handleComboLocation = (event) => {
        setSelectedLocation(event);
        filterAgain("FactoryLocation", event);
    };

    function search(user) {
        return Object.keys(this).every((key) => user[key] === this[key]);
    }

    function filterAgain(type, data) {

        var query = {
            department: type == "Department" ? data : selectedDept,
            factoryLocation: type == "FactoryLocation" ? data : selectedLocation
        }

        let filteredQry = Object.fromEntries(Object.entries(query).filter(([_, v]) => v != null && v != "-SELECT-"));

        var filteredData = props.data.filter(search, filteredQry);
        setMainData(filteredData);
    }


    return (
        <div>
            <div>
                <table className={classes.table}>
                    <thead>
                        <tr>
                            <th>Id</th>
                            <th>Employee Name</th>
                            <th>Department
                                <Combobox
                                    data={departmentCodes}
                                    defaultValue={departmentCodes[0]}
                                    onChange={handleComboDepartment}
                                />
                            </th>
                            <th>Factory Location
                                <Combobox
                                    data={locationCodes}
                                    defaultValue={locationCodes[0]}
                                    onChange={handleComboLocation}
                                />
                            </th>
                        </tr>
                    </thead>
                    <tbody>{mainData.map((ele =>
                        <tr key={nanoid()}>
                            <td>{ele.id}</td>
                            <td>{ele.employeeName}</td>
                            <td>{ele.department}</td>
                            <td>{ele.factoryLocation}</td>
                        </tr>
                    ))}</tbody>
                </table>
            </div>
        </div>
    );
}

export default EmployeeList;

Above code is working totally fine and gives below output

enter image description here

when it change the combo box, then it is displaying data according to the filteration. That works totally fine.

As you can see, the combo box is repetitive (there are 2 combo boxes) and I need it to be defined a combo box as separate component, since React JS concept is to reuse components. (In my above code I repeat it twise) Then I define a new component as CommonCombo.js and modify the EmployeeList.js file.

Here is new EmployeeList file and CommonCombo file

EmployeeList.js

function EmployeeList(props) {
    const [mainData, setMainData] = useState(props.data);

    var departmentCodes = [...new Set(props.data.map(item => item.department))];
    departmentCodes.push("-SELECT-");
    departmentCodes.sort();

    var locationCodes = [...new Set(props.data.map(item => item.factoryLocation))];
    locationCodes.push("-SELECT-");
    locationCodes.sort();
    
    return (
        <div>
            <div>
                <table className={classes.table}>
                    <thead>
                        <tr>
                            <th>Id</th>
                            <th>Employee Name</th>
                            <th>Department
                                <CommonCombo
                                    data={departmentCodes} />

                            </th>
                            <th>Factory Location
                                <CommonCombo
                                    data={locationCodes} />
                            </th>
                        </tr>
                    </thead>
                    <tbody>{mainData.map((ele =>
                        <tr key={nanoid()}>
                            <td>{ele.id}</td>
                            <td>{ele.employeeName}</td>
                            <td>{ele.department}</td>
                            <td>{ele.factoryLocation}</td>
                        </tr>
                    ))}</tbody>
                </table>
            </div>
        </div>
    );
}

export default EmployeeList;

CommonCombo.js

function CommonCombo(props) {

    const handleCombo = (event) => {
        //I need to pass event to EmployeeList.js for filtering data
    };


    return (
        <div>
            <div className={classes.divWidth}>
                <Combobox                
                    data={props.data}
                    defaultValue={props.data[0]}
                    onChange={handleCombo}
                />
            </div>
        </div>
    );
}

export default CommonCombo;

In here (CommonCombo) I need to pass the selected value to EmployeeList.js file for filtering data. I stuck with it. Can any one show me a direction for doing it?

Additional Data:

Used combo box is react-widgets/Combobox.

Employee Sample Data set :

const EmpData = [ { "id": 5486, "employeeName": "John", "department": "HR", "factoryLocation": "Denmark" }, { "id": 5487, "employeeName": "Almeda", "department": "Admin", "factoryLocation": "Austria" }, { "id": 5488, "employeeName": "Kent", "department": "Production", "factoryLocation": "Denmark" }, { "id": 5489, "employeeName": "Peter", "department": "Production", "factoryLocation": "Austria" }, { "id": 5490, "employeeName": "Swargen", "department": "HR", "factoryLocation": "Austria" }, { "id": 5491, "employeeName": "Tim", "department": "Admin", "factoryLocation": "Austria" }, { "id": 5492, "employeeName": "Pat", "department": "HR", "factoryLocation": "Austria" }, { "id": 5492, "employeeName": "Nick", "department": "Marketing ", "factoryLocation": "Denmark" }, { "id": 5493, "employeeName": "Letrim", "department": "Production", "factoryLocation": "Austria" }, { "id": 5494, "employeeName": "Bingo", "department": "HR", "factoryLocation": "Denmark" }, { "id": 5495, "employeeName": "Sarwen", "department": "Production", "factoryLocation": "Denmark" }, ];

CodePudding user response:

Just pass onChange prop to your CommonCombo component

<th>
    Department
    <CommonCombo
        data={departmentCodes} 
        onChange={handleComboDepartment}
    />
</th>
<th>
    Factory Location
    <CommonCombo
        data={locationCodes} 
        onChange={handleComboLocation}
    />
</th>

function CommonCombo(props) {
    return (
        <div>
            <div className={classes.divWidth}>
                <Combobox                
                    data={props.data}
                    defaultValue={props.data[0]}
                    onChange={props.onChange}
                />
            </div>
        </div>
    );
}

CodePudding user response:

You can define a function in your EmployeeList component that receives the event and then filters the data. This function has to be passed via props to your CommonCombo component. Example:

In your EmployeeList component:

function EmployeeList(props) {
  const [mainData, setMainData] = useState(props.data);

  var departmentCodes = [...new Set(props.data.map(item => item.department))];
  departmentCodes.push("-SELECT-");
  departmentCodes.sort();

  var locationCodes = [...new Set(props.data.map(item => item.factoryLocation))];
  locationCodes.push("-SELECT-");
  locationCodes.sort();

  const handleComboData = (data) => {
    // Handle your data coming from CommonCombo component
  }
  
  
  return (
      <div>
          <div>
              <table className={classes.table}>
                  <thead>
                      <tr>
                          <th>Id</th>
                          <th>Employee Name</th>
                          <th>Department
                              <CommonCombo
                                  data={departmentCodes} 
                                  handleComboData={handleComboData}
                                  />

                          </th>
                          <th>Factory Location
                              <CommonCombo
                                  data={locationCodes} 
                                  handleComboData={handleComboData}
                                  />
                          </th>
                      </tr>
                  </thead>
                  <tbody>{mainData.map((ele =>
                      <tr key={nanoid()}>
                          <td>{ele.id}</td>
                          <td>{ele.employeeName}</td>
                          <td>{ele.department}</td>
                          <td>{ele.factoryLocation}</td>
                      </tr>
                  ))}</tbody>
              </table>
          </div>
      </div>
  );
}

export default EmployeeList;

In your CommonCombo component:

function CommonCombo({ data, handleComboData }) {

  const handleCombo = (event) => {
      //I need to pass event to EmployeeList.js for filtering data
      handleComboData(event);
  };


  return (
      <div>
          <div className={classes.divWidth}>
              <Combobox                
                  data={props.data}
                  defaultValue={props.data[0]}
                  onChange={handleCombo}
              />
          </div>
      </div>
  );
}

export default CommonCombo;

Note: the other solution would be to move your change handle functions to the top level component (EmployeeList) and do prop drilling (passing these functions to your CommonCombo and then passing them to Combobox from that point).

  • Related