最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Filter state in React without removing data - Stack Overflow

programmeradmin1浏览0评论

I'm trying to make a react ponent that can filter a list based on value chosen from a drop-down box. Since the setState removes all data from the array I can only filter once. How can I filter data and still keep the original state? I want to be able to do more then one search.

Array list:

  state = {
tree: [
  {
    id: '1',
    fileType: 'Document',
    files: [
        {
          name: 'test1',
          size: '64kb'
        },
        {
          name: 'test2',
          size: '94kb'
        }
    ]
  }, ..... and so on

I have 2 ways that I'm able to filter the ponent once with:

  filterDoc = (selectedType) => {
   //way #1
   this.setState({ tree: this.state.tree.filter(item => item.fileType === selectedType) })

  //way#2
  const myItems = this.state.tree;
  const newArray = myItems.filter(item => item.fileType === selectedType)
  this.setState({
    tree: newArray
  })      
}

Search ponent:

class SearchBar extends Component {

  change = (e) => {
    this.props.filterTree(e.target.value);
  }

  render() {
      return (
        <div className="col-sm-12" style={style}>
            <input
            className="col-sm-8"
            type="text"
            placeholder="Search..."
            style={inputs}
            />
            <select
            className="col-sm-4"
            style={inputs}
            onChange={this.change}
            >
                <option value="All">All</option>
              {this.props.docTypes.map((type) =>
                <option
                  value={type.fileType}
                  key={type.fileType}>{type.fileType}
                </option>)}
            </select>
        </div>
      )
  }
}

And some images just to get a visual on the problem. Before filter:

After filter, everything that didn't match was removed from the state:

I'm trying to make a react ponent that can filter a list based on value chosen from a drop-down box. Since the setState removes all data from the array I can only filter once. How can I filter data and still keep the original state? I want to be able to do more then one search.

Array list:

  state = {
tree: [
  {
    id: '1',
    fileType: 'Document',
    files: [
        {
          name: 'test1',
          size: '64kb'
        },
        {
          name: 'test2',
          size: '94kb'
        }
    ]
  }, ..... and so on

I have 2 ways that I'm able to filter the ponent once with:

  filterDoc = (selectedType) => {
   //way #1
   this.setState({ tree: this.state.tree.filter(item => item.fileType === selectedType) })

  //way#2
  const myItems = this.state.tree;
  const newArray = myItems.filter(item => item.fileType === selectedType)
  this.setState({
    tree: newArray
  })      
}

Search ponent:

class SearchBar extends Component {

  change = (e) => {
    this.props.filterTree(e.target.value);
  }

  render() {
      return (
        <div className="col-sm-12" style={style}>
            <input
            className="col-sm-8"
            type="text"
            placeholder="Search..."
            style={inputs}
            />
            <select
            className="col-sm-4"
            style={inputs}
            onChange={this.change}
            >
                <option value="All">All</option>
              {this.props.docTypes.map((type) =>
                <option
                  value={type.fileType}
                  key={type.fileType}>{type.fileType}
                </option>)}
            </select>
        </div>
      )
  }
}

And some images just to get a visual on the problem. Before filter:

After filter, everything that didn't match was removed from the state:

Share Improve this question asked Jan 13, 2019 at 16:36 PEPEGAPEPEGA 2,28325 silver badges40 bronze badges 2
  • have two property in state one to keep original value and another to keep search results update the result property on search – Code Maniac Commented Jan 13, 2019 at 16:39
  • 1 @CodeManiac I was thinking about that too, but is that really a good approach? – PEPEGA Commented Jan 13, 2019 at 16:45
Add a ment  | 

2 Answers 2

Reset to default 4

Do not replace original data

Instead, change what filter is used and do the filtering in the render() function.

In the example below, the original data (called data) is never changed. Only the filter used is changed.

const data = [
  {
    id: 1,
    text: 'one',
  },
  {
    id: 2,
    text: 'two',
  },
  {
    id: 3,
    text: 'three',
  },
]

class Example extends React.Component {
  constructor() {
    super()
    this.state = {
      filter: null,
    }
  }

  render() {
    const filter = this.state.filter
    const dataToShow = filter
      ? data.filter(d => d.id === filter)
      : data

    return (
      <div>
        {dataToShow.map(d => <span key={d.id}> {d.text}, </span>)}
        <button
          onClick={() =>
            this.setState({
              filter: 2,
            })
          }
        >
          {' '}
          Filter{' '}
        </button>
      </div>
    )
  }
}

ReactDOM.render(<Example />, document.getElementById('root'))
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<body>
  <div id='root' />
</body>

Don't mutate local state to reflect the current state of the filter. That state should reflect the plete available list, which should only change when the list of options changes. Use your filtered array strictly for the view. Something like this should be all you need to change what's presented to the user.

change = (e) => {
   return this.state.tree.filter(item => item.fileType === e.target.value)
}
发布评论

评论列表(0)

  1. 暂无评论