admin管理员组

文章数量:1356877

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

本文标签: javascriptFilter state in React without removing dataStack Overflow