0

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" }, ];

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.