jupiteror
jupiteror

Reputation: 1205

Filtering items with Ant Design List and Radio Group

I would like to create a filter with Ant Design List and Radio Group. When the app is initially loaded I would like to display all items. When a radio button is selected I would like to display only the choices which correspond to its value. I have the following code:

const data = [
  {
    edges: [
      {
        node: {
          name: "A One"
        }
      }
    ],
    category: "A"
  },
  {
    edges: [
      {
        node: {
          name: "B One"
        }
      },
      {
        node: {
          name: "B Two"
        }
      }
    ],
    category: "B"
  }
];

const ArticlesFilter = () => {
  const options = data.map((item) => ({
    label: item.category,
    value: item.category
  }));

  const [value, setValue] = useState("");
  const [articles, setArticles] = useState(data);

  const filterArticles = (data) =>
    data.filter((item) => item.category === value);

  const onChange = (e) => {
    setValue(e.target.value);
    setArticles(filterArticles(data));
  };

  const renderItem = (data) =>
    data.edges.map((item) => (
      <List.Item>
        <Card bordered={false} style={{ width: "100%" }}>
          {item.node.name}
        </Card>
      </List.Item>
    ));

  return (
    <>
      <Radio.Group
        options={options}
        onChange={onChange}
        value={value}
        optionType="button"
      />
      <List dataSource={articles} renderItem={renderItem} />
    </>
  );
};

The problem is that when I select any option for the first time (A or B), no data is displayed at all. When I select any other option next, the data is displayed filtered by the previous value instead of the current value.

Here is the link to my codesandbox. I've added console log to my onChange() function and the render method, and they show different values as well. Where is my mistake? I would really appreciate your help.

Upvotes: 0

Views: 3086

Answers (1)

jean182
jean182

Reputation: 3505

Hey you need to do something slightly different, the onChange event runs very fast so when you're running the setArticles the value state has not changed, to accomplish what you want you can use the useEffect hook that will be listening when the value state changes(when you click a radio item for example) and you can set the articles inside that useEffect, so every-time you change the option, the articles will be filtered:

  useEffect(() => {
   if (value) setArticles(data.filter((item) => item.category === value));
  }, [value])


  const onChange = (e) => {
   setValue(e.target.value);
  };

Here's the forked sandbox in case you want to take a look: https://codesandbox.io/s/antd-radio-group-filter-forked-vx3h6?file=/src/index.js

Also the if (value) condition inside the effect is to avoid filtering an empty string when the component is mounted, since that's your initial value for the value state.

Upvotes: 1

Related Questions