Возвращает количество «ложных» логических значений из массива — MobX

#javascript #reactjs #jsx #mobx #mobx-state-tree

#javascript #reactjs #jsx #mobx #mobx-дерево состояний

Вопрос:

У меня есть макет файла данных, содержимое которого организовано следующим образом:

 {
  id: 6,
  name: 'example',
  time: new Date(),
  viewed: false,
},
  

Моя цель — иметь возможность подсчитывать количество «ложных» значений и возвращать это количество компоненту, который будет использоваться в качестве содержимого.

У меня есть файл, который определяет ModelStore. Начало этого примерно так:

 const Model = types
  .model('Model', {
    id: types.identifierNumber,
    name: types.string,
    time: types.Date,
    viewed: types.boolean,
  });

/** @typedef {typeof Model} Model */
/** @typedef {import('mobx-state-tree').Instance<typeof Model>} ModelInstance */

const ModelStoreData = types.model({ Models: types.array(Model) });
  

Вы можете видеть, что фиктивные данные импортируются в виде массива.

Затем я придумал что-то вроде следующего:

 const ModelStore = types
  .compose(
    ModelStoreData,
  )
  .named('ModelStore')
  .views((self) => {
    /**
     * Count number of unviewed models
     * @returns {typeof self.Models}
     */
    const countUnviewed = (Models) => {
      /**
       * Numerical urgency levels for sorting
       * @enum {number}
       */
      const viewedValues = {
        [true]: 0,
        [false]: 1,
      };

      /** Returns a numerical value */
      const value = Model => viewedValues[Model.viewed];

      return Models
        // do something with value here to add up
    };

    return {
      get unviewedCount() {
        return countUnviewed(self.Models);
      },
    };
  });

/** @typedef {typeof ModelStore} ModelStore */
/** @typedef {import('mobx-state-tree').Instance<typeof ModelStore>} ModelStoreInstance */

export default ModelStore;
  

но я не уверен, как действовать дальше, о том, как на самом деле подсчитать количество «ложных» значений.

Затем у меня есть этот компонент, которому необходимо вставить это подсчитанное значение:

 const myComponent = withRouter(({ history }) => {
  const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);

  const toggle = () => {
    setIsDropdownOpen(prevDropdownOpen => !prevDropdownOpen);
  };

  const handleOnClick = () => {
    history.push(routes.home.path);
  };

  return (
    <Dropdown isOpen={isDropdownOpen} toggle={toggle}>
      <DropdownToggle caret>
        Dropdown
      </DropdownToggle>
      <DropdownMenu right>
        <DropdownItem header>viewed items: 2</DropdownItem>
        <Button outline onClick={handleOnClick}>go home</Button>
      </DropdownMenu>
    </Dropdown>
  );
});
  

где находится «просмотренные элементы: 2», заменяя «2» на подсчитанное значение.

Любые рекомендации относительно того, как подойти к ситуации, были бы оценены.

Ответ №1:

Вы могли бы использовать метод array filter для создания нового массива с каждой моделью, для которой viewed установлено значение false , и возвращать length значение этого массива как unviewedCount .

 const ModelStore = types
  .compose(ModelStoreData)
  .named("ModelStore")
  .views(self => {
    return {
      get unviewedCount() {
        return self.Models.filter(model => !model.viewed).length;
      }
    };
  });
  

Затем вам нужно было бы создать экземпляр ModelStore и использовать observer функцию в вашем компоненте, чтобы ваш компонент повторно отображался в случае unviewedCount изменений.

 const store = ModelStore.create();

const myComponent = withRouter(
  observer(({ history }) => {
    const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);

    const toggle = () => {
      setIsDropdownOpen(prevDropdownOpen => !prevDropdownOpen);
    };

    const handleOnClick = () => {
      history.push(routes.home.path);
    };

    return (
      <Dropdown isOpen={isDropdownOpen} toggle={toggle}>
        <DropdownToggle caret>Dropdown</DropdownToggle>
        <DropdownMenu right>
          <DropdownItem header>
            viewed items: {store.unviewedCount}
          </DropdownItem>
          <Button outline onClick={handleOnClick}>
            go home
          </Button>
        </DropdownMenu>
      </Dropdown>
    );
  })
);
  

Ответ №2:

Вы можете отфильтровать все ложные значения, а затем взять длину отфильтрованных значений.

 let obj = {
  id: 6,
  name: 'example',
  time: new Date(),
  viewed: false,
}

let falseCount = Object.values(obj).filter(e=>!e).length

console.log(falseCount)