Как решить ошибку: "Object is not iterable (cannot read property Symbol(Symbol.iterator))"?

Создал контекст:

const PatientContext = createContext([{}]);

function App() {
  const [selectedPatient, setSelectedPatient] = useState([]);
  const [patients, setPatients] = useState([{ name: "Username", age: 45}]);

  async function patientsHasChanged() {
    const patientService = new PatientService();
    const loadedPatients = await patientService.getPatients();
    setPatients(loadedPatients);
  };

  return (
    <div className='app'>
      <PatientContext.Provider value={[selectedPatient, setSelectedPatient, patients, patientsHasChanged]}>
        <Sidebar />
        <Content />
      </PatientContext.Provider>
    </div>
  );
}

И пытаюсь передать его в дочерний компонент Sidebar:

const Sidebar = () => {
    const [patients, setSelectedPatient] = useContext(PatientContext);

    return (
        <div className='sidebar'>
            <div className='search'>
                <input type="text" placeholder='Search' />
                <a href="/TechTask/new"><button>New patient</button></a>
            </div>
            <div className='list'>
                <ul>
                    {patients.map((p) =>
                        <li onClick={setSelectedPatient}>
                            <div className='name'>
                                {p.name}
                            </div>
                            <div className='age'>
                                {p.age}
                            </div>
                        </li>)
                    }
                </ul>
            </div>
        </div>
    );
};

И получаю ошибку:

TypeError: Object is not iterable (cannot read property Symbol(Symbol.iterator))

Я понимаю, что это из-за того, что нельзя итерировать по объекту, который возвращается, но тогда вопрос: если я в контексте задал масив, то почему возвращается объект и как по нему пройтись, чтобы получить нужные значения?


Ответы (1 шт):

Автор решения: Spatz

Если вы создаете контекст с массивом, то индекс элемента имеет значение. При создании контекста patients идет третьим по счету, а при распаковке контекста вы пытаетесь извлечь его из первой позиции.

Следует либо привести в порядок распаковку контекста:

const [selectedPatient, setSelectedPatient, patients, patientsHasChanged] = useContext(PatientContext);

либо вместо массива использовать в контексте объект:

      <PatientContext.Provider value={{selectedPatient, setSelectedPatient, patients, patientsHasChanged}}>
        <Sidebar />
        <Content />
      </PatientContext.Provider>

(обратите внимание на замену квадратных скобок фигурными). В последнем случае порядок расположения переменных при распаковке может быть произвольным:

const {patients, setSelectedPatient} = useContext(PatientContext);
→ Ссылка