React hooks: useState не устанавливается правильно - PullRequest
0 голосов
/ 11 апреля 2020

Я создал функцию сеттера в родительском компоненте и передал ее дочернему элементу:

Часть, о которой идет речь:

export default function Day({ dayInfo, props }) {
  var [timeOfDay, setTimeOfDay] = useState('');


  function TimeOfDaySetter(index) {
    console.log('index ', index);
    if (index === 0) {
      setTimeOfDay((timeOfDay) => (timeOfDay = 'AM'));
      return <Header as="h1">{timeOfDay}</Header>;
    } else if (index === 12) {
      setTimeOfDay((timeOfDay) => (timeOfDay = 'PM'));
      return <Header as="h1">{timeOfDay}</Header>;
    }
  }

Эта функция вложена в функцию карты у дочернего элемента :

     {Array.from(Array(amountOfRows)).map((row, index) => {
          return (
            <React.Fragment key={index}>
              <Table.Row>
                <Table.Cell rowSpan="2" style={tableStyle}>
                  {TimeOfDaySetter(index)}
                </Table.Cell>

Но это пропускает первое условие?

Может кто-нибудь помочь, почему это происходит?

Завершить Родитель и компонент:

import { Header, Table, TextArea } from 'semantic-ui-react';
import React, { useState, useEffect } from 'react';

export default function Day({ dayInfo, props }) {
  var [dayInfoInChild, setDayInfoInChild] = useState([]);
  var [timeOfDay, setTimeOfDay] = useState('');

  function setExactHourHelper(index) {
    return index === 0 ? 12 : '' || index > 12 ? index - 12 : index;
  }

  function TimeOfDaySetter(index) {
    console.log('index ', index);
    if (index === 0) {
      setTimeOfDay((timeOfDay) => (timeOfDay = 'AM'));
      return <Header as="h1">{timeOfDay}</Header>;
    } else if (index === 12) {
      setTimeOfDay((timeOfDay) => (timeOfDay = 'PM'));
      return <Header as="h1">{timeOfDay}</Header>;
    }
  }

  useEffect(() => {

    if (dayInfo !== null) {
      var modifiedDayInfo = dayInfo
        .split(' ')
        .map((item) => {
          if (item.indexOf(',')) return item.replace(/,/g, '');
        })
        .join('-');

      if (localStorage.getItem(modifiedDayInfo)) {
        // setDayInfoInChild(function (dayInfoInChild) {
        //   return [...setDayInfoInChild, modifiedDayInfo];
        // });
        console.log(modifiedDayInfo);
      } else {
        localStorage.setItem(modifiedDayInfo, JSON.stringify({}));
      }
    }
  }, [dayInfo, timeOfDay, timeOfDay]);

  function TableLayout({ TimeOfDaySetter }) {
    var [amountOfRows, setAmountOfRows] = useState(24);
    var [textValue, setTextValue] = useState('');

    function handleChange(event) {
      setDayInfoInChild(event.target.value);
    }

    const tableStyle = {
      borderLeft: 0,
      borderRight: 0,
    };

    const colorOveride = {
      color: '#C1BDBD',
    };

    return (
      <>
        <h1>{dayInfo}</h1>
        <Table celled structured>
          <Table.Body>
            {Array.from(Array(amountOfRows)).map((row, index) => {
              return (
                <React.Fragment key={index}>
                  <Table.Row>
                    <Table.Cell rowSpan="2" style={tableStyle}>
                      {TimeOfDaySetter(index)}
                    </Table.Cell>
                    <Table.Cell style={tableStyle}>
                      {
                        <strong>
                          {setExactHourHelper(index)}
                          :00
                        </strong>
                      }
                      <TextArea
                        rows={2}
                        name="textarea"
                        value={textValue}
                        onChange={handleChange}
                        placeholder="Tell us more"
                      />
                    </Table.Cell>
                  </Table.Row>
                  <Table.Row>
                    <Table.Cell style={(tableStyle, colorOveride)}>
                      {
                        <strong>
                          {setExactHourHelper(index)}
                          :30
                        </strong>
                      }
                      <TextArea rows={2} placeholder="Tell us more" />
                    </Table.Cell>
                  </Table.Row>
                </React.Fragment>
              );
            })}
          </Table.Body>
        </Table>
      </>
    );
  }

  {
    if (dayInfo === null) {
      return <p>Loading...</p>;
    }
  }

  return (
    <React.Fragment>
      <TableLayout
        dayInfo={dayInfo}
        timeOfDay={timeOfDay}
        TimeOfDaySetter={TimeOfDaySetter}
      />
    </React.Fragment>
  );
}

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

Это должно быть просто setTimeOfDay ("AM") и для второго условного блока setTimeOfDay ("PM"). Вы делаете это слишком сложным, передавая функцию, которая возвращает строку. В то время как вы можете передать функцию, которая возвращает строку, для вашего setTimeOfDay, чтобы установить для нее строку, у вашей функции есть фундаментальная проблема в том, что вы также вручную изменяете состояние.

Обратите внимание, что в вашей функции есть "timeOfDay =" AM "". Это полностью противоречит цели setState и useState, так как вы управляете состоянием напрямую.

У традиционного setState есть вариант использования, когда он может принимать функцию, но я не верю, что useState делает.

// Correct
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});

И эта функция в любом случае не будет вам полезна.

Кроме того, вы используете эффект. Несмотря на то, что ваш эффект использования привязан к [dayInfo, timeOfDay, timeOfDay], он фактически никогда не изменяется, по крайней мере в показанном вами коде. Таким образом, ваш компонент Day получает изменение dayInfo только во время монтирования, а не при повторном рендеринге.

Кроме того, если я что-то упустил, поскольку ваше состояние управляется в вашем компоненте Day, а не в каждом отдельном React Фрагмент, когда вы звоните

{Array.from(Array(amountOfRows)).map((row, index) => {
          return (
            <React.Fragment key={index}>
              <Table.Row>
                <Table.Cell rowSpan="2" style={tableStyle}>
                  {TimeOfDaySetter(index)}
                </Table.Cell>

Вы просто меняете состояние компонента Day с каждой итерацией на карте, что вызывает повторный рендеринг фрагмента реакции. И поэтому будет выполнено только последнее условие, поскольку каждый фрагмент будет перерисован. Было бы лучше передать реквизиты новому элементу компонента вместо вызова состояния на каждой итерации, сделать ваше состояние более сложным для управления каждым фрагментом или управлять своим состоянием локально в каждом компоненте.

0 голосов
/ 11 апреля 2020

Как я вижу, вы передаете функцию стрелки как параметр setTimeOfDay:

setTimeOfDay((timeOfDay) => (timeOfDay = 'AM'));

Вместо этого вы должны вызвать setTimeOfDay как обычный установщик, то есть:

setTimeOfDay('AM');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...