Search code examples
arraysreactjsobjecttypecheckingreact-proptypes

PropTypes: initial useState returns object and fails propTypes check when adding first item


I am not sure in how far this is intended behavior and how much of it is user error;

I initialize a dictionary state as an empty array.

const [dictionary, setDictionary] = useState([]);

Console logging dictionary returns to me an empty array [], while typeof dictionary returns to me an object (why?).

 > []
     length: 0
     __proto__: Array(0)

 > object

The array is eventually propagated by user input in the shape of

[
  {
    word: 'test',
    definition: 'test'
  }
]

I use React's propTypes and check the integrity like this:

Core.propTypes = {
  dictionary: PropTypes.arrayOf(
    PropTypes.objectOf(
      PropTypes.shape({
        definition: PropTypes.string,
        word: PropTypes.string.isRequired
      })
    )
  )
};

On initial render I get no error, but when adding the first item to the array, the console tells me:

Warning: Failed prop type: Invalid prop `dictionary[0].word` of type `string` supplied 
to `Core`, expected `object`.

When changing the PropType check to

WordRandom.propTypes = {
  dictionary: PropTypes.arrayOf(
    PropTypes.objectOf(
      PropTypes.string.isRequired
    )
  )
};

adding the first item does not cause the warning. Am I not supposed to/allowed to check each item in the object?

No subsequent addition to the array triggers the error, so I'm wondering if I goofed something up or if it's intended behavior that doesn't matter?

EDIT: for clarification:

setDictionary([...dictionary, { word, definition }]);

where word and definition are strings


Solution

  • Just use shape

    Shape is already an object. You're adding extra levels that you don't need in your type.

    Core.propTypes = {
      dictionary: PropTypes.arrayOf(
        PropTypes.shape({
          definition: PropTypes.string,
          word: PropTypes.string.isRequired
        })
      )
    };