反应挂钩:useState设置不正确

时间:2020-04-11 16:46:13

标签: reactjs react-hooks use-state

我在父组件中创建了一个setter函数,并将其传递给子组件:

有问题的部分

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 个答案:

答案 0 :(得分:1)

应该简单地将其设置为setTimeOfDay(“ AM”),对于第二个条件块setTimeOfDay(“ PM”)。通过传递一个返回字符串的函数,使它变得过于复杂。虽然您可以传入一个返回字符串的函数,但setTimeOfDay可以将其设置为字符串,但是该函数存在一个根本性的问题,即您还需要手动更改状态。

在函数中,您有“ timeOfDay ='AM'”。因为您直接操纵状态,所以这完全违反了setState和useState的目的。

传统的setState确实具有用例,它可以接受一个函数,但是我不相信useState可以。

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

无论如何,此功能现在对您都没有用。

此外,在您的useEffect中。即使您已将您的使用效果与[dayInfo,timeOfDay,timeOfDay]绑定在一起,但至少在所显示的代码中,它实际上从未被修改过。因此,您的Day组件只会在安装过程中获得dayInfo的更改,而无需重新渲染。

另外,除非我丢失了某些内容,否则在调用

时,因为状态是在Day组件中管理的,而不是在每个单独的React Fragment中管理的
{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组件的状态,这将导致您的react片段重新呈现。因此,仅满足最后一个条件,因为每个片段都会重新渲染。最好将props传递给新的组件项目,而不是在每次迭代时都调用状态,使状态变得更复杂以管理每个片段,或者在每个组件内本地管理状态。

答案 1 :(得分:-1)

如我所见,您将箭头函数作为setTimeOfDay参数传递:

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

相反,您应该将setTimeOfDay作为通常的设置方法调用,即:

setTimeOfDay('AM');