1

Disclaimer: I know the topic is very unspecific. But I don't know how to describe my issue better. Feel free to help me in the comments and I'll update it later.


I fetch an array of objects coming from a MySQL database to my React App Component. It has this structure:

const fetchedData = [
    {
        "id":         46923,
        "type":       "Change Request",
        "business":   "Systems",
        "owner":      "Max",
        "created_on": "2019-08-16T05:39:00.000Z",
        "many more":  "values",
    },
    {
        "id":         46924,
        "type":       "Change Notice",
        "business":   "Tools",
        "owner":      "Max",
        "created_on": "2019-09-06T11:19:00.000Z",
        "many more":  "values",
    },
]

The type can have three values only:

  • Change Request
  • Change Notice
  • Change Task

The business can have three values only:

  • Systems
  • Tools
  • Misc

I have a react component that has checkboxes for each value:

function ControlBoard({ applyFilter }) {
  const classes = useStyles();

  const [state, setState] = useState({
    business: {
      systems: false,
      tools: false,
      misc: false,
    },
    type: {
      changerequest: false,
      changenotice: false,
      changetask: false,
    },
  });

  const handleChange = (event) => {
    const split = event.target.name.split("|");
    const group = split[0];
    const name = split[1];
    let prop = state;
    prop[group][name] = event.target.checked;
    setState({ ...prop });
  };

  const setFilter = () => {
    applyFilter(state);
  };

  useEffect(() => {
    setFilter();
  }, [state]);

  return (
    <div className={classes.root}>
      <div className={classes.title}>Businesses</div>
      <div className={classes.items}>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.systems}
                onChange={handleChange}
                name="business|systems"
                color="primary"
              />
            }
            label="Systems"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.tools}
                onChange={handleChange}
                name="business|tools"
                color="primary"
              />
            }
            label="Tools"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.business.misc}
                onChange={handleChange}
                name="business|misc"
                color="primary"
              />
            }
            label="Misc"
          />
        </div>
      </div>

      <div className={classes.title}>Type</div>
      <div className={classes.items}>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changerequest}
                onChange={handleChange}
                name="type|changerequest"
                color="primary"
              />
            }
            label="Change Request"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changenotice}
                onChange={handleChange}
                name="type|changenotice"
                color="primary"
              />
            }
            label="Change Notice"
          />
        </div>
        <div className={classes.item}>
          <FormControlLabel
            control={
              <Checkbox
                checked={state.type.changetask}
                onChange={handleChange}
                name="type|changetask"
                color="primary"
              />
            }
            label="Change Task"
          />
        </div>
      </div>
    </div>
  );
}

export default ControlBoard;

Thus I have my state object:

{
   business: {
      systems: false,
      tools: false,
      misc: false,
   },
   type: {
      changerequest: false,
      changenotice: false,
      changetask: false,
   },
}

How can I filter my fetchedData array against my state? Each combination of boolean values (including multiple true values of business and type) is possible. Later there will be more values than business and type.

To check against the fetched data values it could be possible to use e.g.:

state.type[0].toUpperCase() === fetchedDataRow.type.toUpperCase().replace(" ", "")

3 Answers 3

1

You can create a match function like this using the object keys, here we go through each key of the state and the values and if any of it has true we check it.

You can see the output below

const fetchedData = [{
    "id": 46923,
    "type": "Change Request",
    "business": "Systems",
    "owner": "Max",
    "created_on": "2019-08-16T05:39:00.000Z",
    "many more": "values",
  },
  {
    "id": 46924,
    "type": "Change Notice",
    "business": "Tools",
    "owner": "Max",
    "created_on": "2019-09-06T11:19:00.000Z",
    "many more": "values",
  },
]

const state = {
  business: {
    systems: true,
    tools: true,
    misc: false,
  },
  type: {
    changerequest: false,
    changenotice: false,
    changetask: false,
  },
};


const isMatch = (criteria, item) => {
  let output = true;

  Object.keys(criteria).forEach((element) => {
    const shouldCheck = Object.keys(criteria[element]).some((x) => (criteria[element][x]));

    if (shouldCheck) {
      output = output && Object.keys(criteria[element]).some((x) => {
        return criteria[element][x] && x.toUpperCase() === item[element].toUpperCase().replace(" ", "");
      });
    }
  });
  return output;
};


console.log(fetchedData.filter(x => isMatch(state, x)))

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

6 Comments

This is a great and helpful answer, but it is not working if multiple business or type values are true. E.g. {business: {systems: true, tools: true, misc: false}, type: {changerequest: true, changenotice: true, changetask: false}}
It's getting closer. Now, when I filter for multiple businsses, it is ignoring the business value of types. That means, when I check tools and systems it's fine. When I add Change Request, it is adding every change request no matter what the business is.
let me check this and get back to you
@T.Karter can you check now please :)
That's it! Great!
|
0

Rather than creating all the field in the object. How about creating an array in which only those values present on which you wants to apply the filter. In this case you don't have to maintain all the field state.

 var filter = {
        business: ['systems','tools'],
        type: ['changerequest']
 };

And create a filter base on that filter criteria like below:-

const fetchedData = [{
    "id": 46923,
    "type": "Change Request",
    "business": "Systems",
    "owner": "Max",
    "created_on": "2019-08-16T05:39:00.000Z",
    "many more": "values",
  },
  {
    "id": 46924,
    "type": "Change Notice",
    "business": "Tools",
    "owner": "Max",
    "created_on": "2019-09-06T11:19:00.000Z",
    "many more": "values",
  }
];

var filter = {
        business: ['Systems','tools'],
        type: ['Change Request']
 };

var result = fetchedData.filter(item => {
   for (var key in filter) {
      return filter[key].indexOf(item[key]) != -1;
   }
});

console.log(result);

Comments

0

.toLowerCase() and replace(' ','') are used to form the fetchedData to match to state keys.

const fetchedData = [{
    "id": 46923,
    "type": "Change Request",
    "business": "Systems",
    "owner": "Max",
    "created_on": "2019-08-16T05:39:00.000Z",
    "many more": "values",
  },
  {
    "id": 46924,
    "type": "Change Notice",
    "business": "Tools",
    "owner": "Max",
    "created_on": "2019-09-06T11:19:00.000Z",
    "many more": "values",
  },
]

const state = {
  business: {
    systems: false,
    tools: true,
    misc: false,
  },
  type: {
    changerequest: false,
    changenotice: true,
    changetask: false,
  },
}

const result = fetchedData.filter((obj) => {
  let businessMatch = false;
  let typeMatch = false;
  for (const [key, value] of Object.entries(state.business)) {
    if (key === obj.business.toLowerCase() && value) {
      businessMatch = true;
      break;
    } else {
      businessMatch = false
    }
  }

  for (const [key, value] of Object.entries(state.type)) {
    if (key === obj.type.toLowerCase().replace(' ', '') && value) {
      typeMatch = true;
      break;
    } else {
      typeMatch = false
    }
  }

  if (businessMatch && typeMatch) return obj;
})

console.log(result)

1 Comment

This code is not checking for any combination. There can be multiple true values for business and type

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.