Проблема с фильтром по флажку [reactjs]

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я пытаюсь настроить фильтрацию по флажку в React.

То, что я хочу, чтобы произошло, это:

  1. Пользователь переходит к продуктам, где все продукты отображаются при загрузке страницы.
  2. Пользователь устанавливает флажок, и отображаются отфильтрованные продукты.
  3. Снятие флажка приведет к повторному возврату всех продуктов.

То, что в настоящее время происходит, это:

  1. Пользователь переходит к продуктам, продукты не отображаются.
  2. Пользователь устанавливает флажок, возвращаются отфильтрованные продукты.
  3. Снимите флажок, все товары будут возвращены.

Итак, это почти готово, но чего-то не хватает для начальной загрузки страницы, может кто-нибудь, пожалуйста, посоветовать, что я пропустил?

Примерные данные =

     console.log(checkedInputs) = Object { 35: true }
    console.log(Item) = Object { itemID: "5190", systemSku: "item", defaultCost: "78.95", avgCost: "78.95", discountable: "true", tax: "true", archived: "false", itemType: "default", serialized: "false", description: "item", … }Object { itemID: "5191", systemSku: "item", defaultCost: "142.95", avgCost: "142.95", discountable: "true", tax: "true", archived: "false", itemType: "default", serialized: "false", description: "item", … }
 

При начальной загрузке страницы checkedInputs =

 console.log(checkedInputs = Object { })
 

Спасибо!


Products.jsx

 const Products = (props) => {
  const { Item } = props.items
  const { Category } = props.categories

  const [checkedInputs, setCheckedInputs] = useState({})

  const handleInputChange = (event) => {
    setCheckedInputs({ ...checkedInputs, [event.target.value]: event.target.checked })
  }

  useEffect(() => {
    console.log('Checked Inputs', checkedInputs)
  }, [checkedInputs])

  return (
    <Layout>
      <div className="flex mx-96">
        <div className="w-1/4">
          <ProductFilter category={Category} handleInputChange={handleInputChange} checkedInputs={checkedInputs} />
        </div>
        <div className="w-3/4">
          <div className="lg:grid grid-cols-3 gap-2 lg:my-12 lg:justify-center">
            {Item.map(item => {
              for (const [key, value] of Object.entries(checkedInputs)) {
                if (!checkedInputs || Object.keys(checkedInputs).every(value => checkedInputs[value] === false)) {
                  return <ProductCard item={item} key={item.itemID} />
                }
                if (value === true) {
                  if (item.categoryID === key) {
                    console.log(item)
                    return <ProductCard item={item} key={item.itemID} />
                  }
                }
              }
            })}
          </div>
        </div>
      </div>
    </Layout>
  )
}
 

Комментарии:

1. можете ли вы поделиться структурой данных? (Item и checkedInputs)

2. Конечно, я добавлю это выше.

3. это выглядит так сложно, items — это массив объектов. каждый объект добавляет свойство отображения по умолчанию true. при нажатии на флажок все отображение продукта преобразуется в false, кроме того, на кого нажат.

Ответ №1:

Я не уверен, что это проблема, но вы, я думаю, хотите изменить

 if (!checkedInputs || Object.keys(checkedInputs).every(value => checkedInputs[value] === false)) {
  return <ProductCard item={item} key={item.itemID} />
}
 

Для

 if (Object.keys(checkedInput).length < 1 || Object.keys(checkedInputs).every(value => checkedInputs[value] === false)) {
  return <ProductCard item={item} key={item.itemID} />
}
 

Пустой объект оценивается как true. Я думаю, что объект всегда будет оценивать значение true. (Try Boolean({}) and Boolean({x:5})) . Кроме того, я немного сбит с толку (я мог что-то упустить) относительно того, почему вы вызываете Object.keys(checkedInputs).каждый на каждой итерации Object.entries(checkedInputs). Это значение не меняется, верно? Так не может ли это быть статическое значение, которое вы установили перед циклом?

Комментарии:

1. Я понимаю, к чему вы клоните с этим ответом, к сожалению, это не решает проблему. Возможно, мне не нужно это делать 🙂

2. Исправлено в указанном вами порядке! Спасибо!

3. И ‘Object.keys(checkedInput). длина <1’

Ответ №2:

 const Products = (props) => {
  const { Item } = props.items
  const { Category } = props.categories

  const [checkedInputs, setCheckedInputs] = useState({})

  const handleInputChange = (event) => {
    setCheckedInputs({ ...checkedInputs, [event.target.value]: event.target.checked })
  }

  useEffect(() => {
    console.log('Checked Inputs', checkedInputs)
  }, [checkedInputs])
  function renderItems(){
    let hasNoFilters = Object.keys(checkedInput).length < 1 || 
      Object.keys(checkedInputs).every(value =>checkedInputs[value] === false)
    if(hasNoFilters){
      // return everything if no filter
      return Item.map(item=>return <ProductCard item={item} key={item.itemID} />)
    }
    else{
      let filters = Object.keys(checkedInput).filter(itemID=>checkedInput[itemID] === true)
      return Item.map(item=>{
        //check to make sure itemID is found in filters
        let validItem = filters.find(itemID=>itemID === item.itemID)
        if(!validItem)
          return
        return <ProductCard item={item} key={item.itemID} />
      })
    }
  }  
  return (
    <Layout>
      <div className="flex mx-96">
        <div className="w-1/4">
          <ProductFilter category={Category} handleInputChange={handleInputChange} checkedInputs={checkedInputs} />
        </div>
        <div className="w-3/4">
          <div className="lg:grid grid-cols-3 gap-2 lg:my-12 lg:justify-center">
            {renderItems()}
          </div>
        </div>
      </div>
    </Layout>
  )
}