title: How to filter on ANTD table when the column is a JSON array instead of a string
body: <p>I have an antd table with 2 columns which I need to filter on the first, and search text on the second column.</p>
  
  <p>From my code, the application is rendered fine.  Please note the tags field is a json array, not a text field, so I guess that has something to do  with the error.</p>
  
  <p>Updated 1 Code.</p>
  
  <pre><code>import React, { Component } from 'react';
  import {  Table, Tag, Button, Icon, Input} from 'antd';
  import { adalApiFetch } from '../../adalConfig';
  import Notification from '../../components/notification';
  import Highlighter from 'react-highlight-words';
  
  class ListPageTemplatesWithSelection extends Component {
  
      constructor(props) {
          super(props);
          this.state = {
              data: [],
              filteredInfo: null,
              sortedInfo: null,
              searchText: ''
          };
          this.handleChange= this.handleChange.bind(this);
          this.clearFilters= this.clearFilters.bind(this);
          this.clearAll= this.clearAll.bind(this);
          this.getColumnSearchProps= this.getColumnSearchProps.bind(this);
          this.handleSearch= this.handleSearch.bind(this);
          this.handleReset= this.handleReset.bind(this);
  
      }
  
      handleSearch (selectedKeys, confirm){
        confirm();
        this.setState({ searchText: selectedKeys[0] });
      }
  
      handleReset(clearFilters){
        clearFilters();
        this.setState({ searchText: '' });
      }
  
      getColumnSearchProps = (dataIndex) =&gt; ({
          filterDropdown: ({
          setSelectedKeys, selectedKeys, confirm, clearFilters,
        }) =&gt; (
          &lt;div style={{ padding: 8 }}&gt;
            &lt;Input
              ref={node =&gt; { this.searchInput = node; }}
              placeholder={`Search ${dataIndex}`}
              value={selectedKeys[0]}
              onChange={e =&gt; setSelectedKeys(e.target.value ? [e.target.value] : [])}
              onPressEnter={() =&gt; this.handleSearch(selectedKeys, confirm)}
              style={{ width: 188, marginBottom: 8, display: 'block' }}
            /&gt;
            &lt;Button
              type="primary"
              onClick={() =&gt; this.handleSearch(selectedKeys, confirm)}
              icon="search"
              size="small"
              style={{ width: 90, marginRight: 8 }}
            &gt;
              Search
            &lt;/Button&gt;
            &lt;Button
              onClick={() =&gt; this.handleReset(clearFilters)}
              size="small"
              style={{ width: 90 }}
            &gt;
              Reset
            &lt;/Button&gt;
          &lt;/div&gt;
        ),
        filterIcon: filtered =&gt; &lt;Icon type="search" style={{ color: filtered ? '#1890ff' : undefined }} /&gt;,
        onFilter: (value, record) =&gt;
        record[dataIndex]
          ? record[dataIndex]
              .toString()
              .toLowerCase()
              .includes(value.toLowerCase())
          : false,
        onFilterDropdownVisibleChange: (visible) =&gt; {
          if (visible) {
            setTimeout(() =&gt; this.searchInput.select());
          }
        }
      })
  
      handleChange(pagination, filters, sorter){
        console.log('Various parameters', pagination, filters, sorter);
        this.setState({
          filteredInfo: filters,
          sortedInfo: sorter,
        });
      }
  
      clearFilters(){
        this.setState({ filteredInfo: null });
      }
  
      clearAll(){
        this.setState({
          filteredInfo: null,
          sortedInfo: null,
        });
      }
  
      fetchData = () =&gt; {
          adalApiFetch(fetch, "/PageTemplates", {})
            .then(response =&gt; response.json())
            .then(responseJson =&gt; {
              if (!this.isCancelled) {
                  const results= responseJson.map(row =&gt; ({
                      key: row.Id,
                      Name: row.Name,
                      SiteType: row.SiteType,
                      Tags: row.Tags
                    }))
                this.setState({ data: results });
              }
            })
            .catch(error =&gt; {
              console.error(error);
            });
        };
  
  
      componentDidMount(){
          this.fetchData();
      }
  
      render(){
            let { sortedInfo, filteredInfo } = this.state;
          sortedInfo = sortedInfo || {};
          filteredInfo = filteredInfo || {};
  
          const columns = [
                  {
                      title: 'Id',
                      dataIndex: 'key',
                      key: 'key',
                  }, 
                  {
                      title: 'Name',
                      dataIndex: 'Name',
                      key: 'Name',
                  }, 
                  {
                      title: 'Site Type',
                      dataIndex: 'SiteType',
                      key: 'SiteType',
                      filters: [
                        { text: 'Modern Team Site', value: 'Modern Team Site' },
                        { text: 'CommunicationSite', value: 'CommunicationSite' },
                      ],
                      filteredValue: filteredInfo.SiteType || null,
                      onFilter: (value, record) =&gt; record.SiteType.includes(value),
                  },{
                    title: 'Tags',
                    key: 'Tags',
                    dataIndex: 'Tags',
                    ...this.getColumnSearchProps('Tags'),
                    render: Tags =&gt; (
                      &lt;span&gt;
                      {Tags &amp;&amp; Tags.map(tag =&gt; {
                        let color = tag.length &gt; 5 ? 'geekblue' : 'green';
                        if (tag === 'loser') {
                          color = 'volcano';
                        }
                        return &lt;Tag color={color} key={tag}&gt;{tag.toUpperCase()}&lt;/Tag&gt;;
                      })}
                    &lt;/span&gt;)
  
                  }
          ];
  
          const rowSelection = {
              selectedRowKeys: this.props.selectedRows,
              onChange: (selectedRowKeys) =&gt; {
                this.props.onRowSelect(selectedRowKeys);
              }
            };
  
  
          return (
            &lt;div&gt;
              &lt;Button onClick={this.clearFilters}&gt;Clear filters&lt;/Button&gt;
              &lt;Button onClick={this.clearAll}&gt;Clear filters and sorters&lt;/Button&gt;
              &lt;Table rowSelection={rowSelection}  columns={columns} dataSource={this.state.data} onChange={this.handleChange} /&gt;
            &lt;/div&gt;
          );
      }
  }
  
  export default ListPageTemplatesWithSelection;
  </code></pre>
  
  <p>However when I add this line:
  <code>...this.getColumnSearchProps('Tags'),</code></p>
  
  <p>Then I get this error</p>
  
  <pre><code>Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
  ▶ 23 stack frames were collapsed.
  AsyncFunc._callee$
  src/helpers/AsyncFunc.js:26
    23 | const { default: Component } = await importComponent();
    24 | Nprogress.done();
    25 | if (this.mounted) {
  &gt; 26 |   this.setState({
    27 |     component: &lt;Component {...this.props} /&gt;
    28 |   });
    29 | }
  </code></pre>
  
  <p>Update 2</p>
  
  <p>This is the container component</p>
  
  <pre><code>import React, { Component } from 'react';
  import { Input} from 'antd';
  import Form from '../../components/uielements/form';
  import Button from '../../components/uielements/button';
  import Notification from '../../components/notification';
  import { adalApiFetch } from '../../adalConfig';
  import   ListPageTemplatesWithSelection  from './ListPageTemplatesWithSelection';
  
  const FormItem = Form.Item;
  
  class CreateCommunicationSiteCollectionForm extends Component {
      constructor(props) {
          super(props);
          this.state = {Title:'',Url:'', SiteDesign:'', Description:'',Owner:'',Lcid:'', PageTemplateIds : []};
          this.handleChangeTitle = this.handleChangeTitle.bind(this);
          this.handleValidationCommunicationSiteUrl = this.handleValidationCommunicationSiteUrl.bind(this);
          this.handleChangeCommunicationSiteUrl = this.handleChangeCommunicationSiteUrl.bind(this);
          this.handleChangeSiteDesign = this.handleChangeSiteDesign.bind(this);
          this.handleChangeDescription = this.handleChangeDescription.bind(this);
          this.handleChangeOwner = this.handleChangeOwner.bind(this);
          this.handleChangelcid = this.handleChangelcid.bind(this);
  
          this.handleSubmit = this.handleSubmit.bind(this);
          this.handleRowSelect = this.handleRowSelect.bind(this);
      }
  
      handleRowSelect(ids) {
          this.setState({ PageTemplateIds: ids });
      }
  
      handleChangeTitle(event){
          this.setState({Title: event.target.value});
      }
  
      handleValidationCommunicationSiteUrl(rule, value, callback){
          const form = this.props.form;
          const str = form.getFieldValue('communicationsiteurl');        
          var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&amp;'\(\)\*\+,;=.]+$/i;
          if (str &amp;&amp; !str.match(re)) {
              callback('Communication site url is not correctly formated.');
          } 
          else {
              callback();
          }
      }
  
      handleChangeCommunicationSiteUrl(event){
          this.setState({Url: event.target.value});
      }
  
      handleChangeSiteDesign(event){
          this.setState({SiteDesign: event.target.value});
      }
  
      handleChangeDescription(event){
          this.setState({Description: event.target.value});
      }
  
      handleChangeOwner(event){
          this.setState({Owner: event.target.value});
      }
  
      handleChangelcid(event){
          this.setState({Lcid: event.target.value});
      }
  
      handleSubmit(e){
          e.preventDefault();
          this.props.form.validateFieldsAndScroll((err, values) =&gt; {
              if (!err) {
                  let data = new FormData();
                  //Append files to form data
                  //data.append(
  
                  const options = {
                    method: 'post',
                    body: JSON.stringify(
                      {
                          "Title": this.state.Title,
                          "Url": this.state.Url, 
                          "SiteDesign": this.state.SiteDesign,
                          "Description": this.state.Description,
                          "Owner": this.state.Owner,
                          "Lcid": this.state.Lcid,
                          "PageTemplateIds": this.state.PageTemplateIds
                      }),
                      headers: {
                              'Content-Type': 'application/json; charset=utf-8'
                      }                    
                  };
  
                  adalApiFetch(fetch, "/SiteCollection/CreateCommunicationSite", options)
                    .then(response =&gt;{
                      if(response.status === 201){
                          Notification(
                              'success',
                              'Communication Site created',
                              ''
                              );
                       }else{
                          throw "error";
                       }
                    })
                    .catch(error =&gt; {
                      Notification(
                          'error',
                          'Site collection not created',
                          error
                          );
                      console.error(error);
                  });
              }
          });      
      }
  
      render() {
          const { getFieldDecorator } = this.props.form;
          const formItemLayout = {
          labelCol: {
              xs: { span: 24 },
              sm: { span: 6 },
          },
          wrapperCol: {
              xs: { span: 24 },
              sm: { span: 14 },
          },
          };
          const tailFormItemLayout = {
          wrapperCol: {
              xs: {
              span: 24,
              offset: 0,
              },
              sm: {
              span: 14,
              offset: 6,
              },
          },
          };
          return (
              &lt;Form onSubmit={this.handleSubmit}&gt;
                  &lt;FormItem {...formItemLayout} label="Title" hasFeedback&gt;
                  {getFieldDecorator('Title', {
                      rules: [
                          {
                              required: true,
                              message: 'Please input your communication site title',
                          }
                      ]
                  })(&lt;Input name="title" id="title" onChange={this.handleChangeTitle} /&gt;)}
                  &lt;/FormItem&gt;
                  &lt;FormItem {...formItemLayout} label="Communication Site Url" hasFeedback&gt;
                  {getFieldDecorator('communicationSiteUrl', {
                      rules: [
                          {
                              required: true,
                              message: 'CommunicationSite site collection url',
                          },
                          {
                              validator: this.handleValidationCommunicationSiteUrl
                          }
                      ]
                  })(&lt;Input name="communicationsSiteUrl" id="communicationsSiteUrl" onChange={this.handleChangeCommunicationSiteUrl} /&gt;)}
                  &lt;/FormItem&gt;
                  &lt;FormItem {...formItemLayout} label="Site Design" hasFeedback&gt;
                  {getFieldDecorator('sitedesign', {
                      rules: [
                          {
                              required: true,
                              message: 'Please input your site design',
                          }
                      ]
                  })(&lt;Input name="sitedesign" id="sitedesign" onChange={this.handleChangeSiteDesign} /&gt;)}
                  &lt;/FormItem&gt;
                  &lt;FormItem {...formItemLayout} label="Description" hasFeedback&gt;
                  {getFieldDecorator('description', {
                      rules: [
                          {
                              required: true,
                              message: 'Please input your description',
                          }
                      ],
                  })(&lt;Input name="description" id="description"  onChange={this.handleChangeDescription} /&gt;)}
                  &lt;/FormItem&gt;
                  &lt;FormItem {...formItemLayout} label="Owner" hasFeedback&gt;
                  {getFieldDecorator('owner', {
                      rules: [
                          {
                              required: true,
                              message: 'Please input your owner',
                          }
                      ],
                  })(&lt;Input name="owner" id="owner"  onChange={this.handleChangeOwner} /&gt;)}
                  &lt;/FormItem&gt;
                  &lt;FormItem {...formItemLayout} label="Lcid" hasFeedback&gt;
                  {getFieldDecorator('lcid', {
                      rules: [
                          {
                              required: true,
                              message: 'Please input your lcid',
                          }
                      ],
                  })(&lt;Input name="lcid" id="lcid"  onChange={this.handleChangelcid} /&gt;)}
                  &lt;/FormItem&gt;          
  
                  &lt;ListPageTemplatesWithSelection onRowSelect={this.handleRowSelect} selectedRows={this.state.PageTemplateIds}/&gt;
  
  
                  &lt;FormItem {...tailFormItemLayout}&gt;
                      &lt;Button type="primary" htmlType="submit"&gt;
                          Create communication site
                      &lt;/Button&gt;
                  &lt;/FormItem&gt;
  
  
              &lt;/Form&gt;
  
  
  
          );
      }
  }
  
  const WrappedCreateCommunicationSiteCollectionForm = Form.create()(CreateCommunicationSiteCollectionForm);
  export default WrappedCreateCommunicationSiteCollectionForm;
  </code></pre>