Есть ли способ создать динамическое состояние и setState в React

#javascript #reactjs #redux

#javascript #reactjs #redux

Вопрос:

У меня следующее замедление: const [open1, setOpen1] = useState(false);

и я хотел бы сгенерировать это столько, сколько я извлекаю записей из базы данных (для каждой извлеченной записи), мне нужен new [open, setopen]

вот мой цикл for, используемый в моем коде.

         <Container fluid={true} className="text-center">
          <div
            className="questionrectangle "
            onClick={() => setOpen1(!open1)}
            name="step-one"
            aria-controls="example-collapse-text"
            aria-expanded={open1}>
            <p className="questiontext "> {post.QString}</p>
          </div>
          <Collapse in={open1} name="step-two">
            <p className="questionanswer">{post.Answer}</p>
          </Collapse>
        </Container> ```

If you have any idea I would be appreciated 
 

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

1. Это не очень хорошая идея. Почему вы не хотите иметь дело setOpen только один раз в Container ?

2. Когда я использую его только один раз, это влияет на другие элементы. я имею в виду, что все элементы сворачиваются вместе, когда я нажимаю на один из них.

3. Правильно, вам нужно будет настроить prop с уникальным идентификатором. Тогда ваш эффект будет применяться к конкретному дочернему Collapse компоненту с этим идентификатором.

4. Я попробую это. Спасибо.

5. вы должны передать полученные данные на аутсорсинг в компонент и иметь там состояние setopen, чтобы каждый выбранный элемент имел свое собственное состояние … вот как работает поток реакции

Ответ №1:

Создайте отдельный компонент для сохранения состояния «open». Что-то вроде этого..

 function QuestionAnswer({post}) {
  const [open1, setOpen1] = useState(true);

  return (
    <>
      <div
        className="questionrectangle "
        onClick={() => setOpen1(!open1)}
        name="step-one"
        aria-controls="example-collapse-text"
        aria-expanded={open1}
      >
        <p className="questiontext "> {post.QString}</p>
      </div>
      {open1 amp;amp; (
        <div name="step-two">
          <p className="questionanswer">{post.Answer}</p>
        </div>
      )}
    </>
  );
}
 

Теперь из вашего основного приложения извлеките данные и создайте один компонент для каждого сообщения — вот так

   // Replace this with fetch request
  const data = [
    { QString: "Question 1", Answer: "answer 1" },
    { QString: "Question 2", Answer: "answer 2" },
    { QString: "Question 3", Answer: "answer 3" }
  ];

  return (
    <Container fluid={true} className="text-center">
      {data.map((post) => (
        <QuestionAnswer post={post} />
      ))}
    </Container>
  );
}
 

Теперь каждый компонент будет содержать свою собственную копию «открытого» состояния и сможет обрабатывать отдельные открытые и закрытые состояния.

Вы можете увидеть полный образец

https://codesandbox.io/s/beautiful-surf-ejron

Ответ №2:

Хитрость в том, чтобы думать об этом, заключается в том, что каждый дочерний элемент (ваш список <Containers /> ) не должен отвечать за знание о своих братьях и сестрах или о том, как ответственно управлять открытым состоянием между ними, не вызывая конфликтов. Эта ответственность должна быть на один уровень выше, что-то, что может видеть всех дочерних элементов и управлять ими для них.

Должно быть легко принять этот пример аккордеона для вашего собственного использования.

 const DocsManager = () => {
  // Manage which step is open here, at a higher level
  const [openIndex, setOpenIndex] = useState(0); // or whatever the default should be
  // Records could live here, or be passed in as props
  const [docs, setDocs] = useState([]);

  useEffect(() => {
    getDocs.then(setDocs);
  }, [])

  return docs.map((doc, i) =>
    <YourComponent
      isOpen={openIndex === i}
      // Or maybe
      open={() => setOpenIndex(i)}
      // Or maybe
      close={() => setOpenIndex(null)}
      // Or maybe
      next={() => setOpenIndex(openIndex   1)}
      doc={doc}
    />
  );
};