React 中附加数组值而不是显示新值列表

问题描述 投票:0回答:4

场景 -

默认在文本字段中输入数字 - 1

列出的项目 -

  • 1
  • 6
  • 11

现在,一旦我从文本字段中删除 1 -

列出项目 -

  • NaN
  • NaN
  • NaN

现在在输入字段中输入4

列出项目 -

  • NaN
  • NaN
  • 4
  • 9
  • 14

预期行为 -

列表项应仅显示 -

4, 9 and 14
而不是
NaN, NaN, 4, 9, 14

让我知道我在这里做错了什么。

代码-

import React, { useState } from "react";
import List from "./List";

const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(parseInt(e.target.value, 10))}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

export default ReRendering;

List.js

import { useEffect, useState } from "react";

const List = ({ getList }) => {
  const [item, setItem] = useState([]);

  useEffect(() => {
    setItem(getList());
  }, [getList]);
  return (
    <div className="list">
      {item.map((x) => (
        <div key={x}>{x}</div>
      ))}
    </div>
  );
};

export default List;

工作示例 - https://codesandbox.io/s/gallant-gagarin-l18ni1?file=/src/ReRendering.js:0-463

javascript reactjs react-state
4个回答
4
投票

如果输入字段为空,执行

setNumber(parseInt(e.target.value, 10))
会将数字状态设置为
NaN
,因为空字符串不能为
parseInt
d。

console.log(parseInt(''));

NaN 会导致问题,因为正如 React 警告所说:

警告:遇到两个孩子使用同一把钥匙,

NaN
。密钥应该是唯一的,以便组件在更新时保持其身份。非唯一的键可能会导致子项重复和/或省略 - 该行为不受支持,并且可能在未来版本中更改。

重复的 NaN 会导致重复的键。

相反,请使用

valueAsNumber
,如果该值不存在,则与 0 交替。

const { useState, useEffect } = React;
const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.valueAsNumber || 0)}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

const List = ({ getList }) => {
  const [item, setItem] = useState([]);
  useEffect(() => {
    setItem(getList());
  }, [getList]);
  return (
    <div className="list">
      {item.map((x) => (
        <div key={x}>{x}</div>
      ))}
    </div>
  );
};


ReactDOM.render(<ReRendering />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

构建此结构的更好方法是立即在子级中调用

getList
,而不是在其中使用单独的状态和效果钩子。

const { useState, useEffect } = React;
const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.valueAsNumber || 0)}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

const List = ({ getList }) => (
  <div className="list">
    {getList().map((x) => (
      <div key={x}>{x}</div>
    ))}
  </div>
);


ReactDOM.render(<ReRendering />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>


1
投票

进行以下更改,它应该会产生您想要的结果。

它基本上考虑输入为空的情况,并告诉它在没有提供输入时不显示任何内容。

List.js


import { useEffect, useState } from "react";

const List = ({ getList }) => {
  const [item, setItem] = useState([]);

  useEffect(() => {
    setItem(getList());
  }, [getList]);
  return (
    <div className="list">
      {item ? item.map((x) => (               // changes
        <div key={x}>{x}</div>
      )):""}
    </div>
  );
};

export default List;


重新渲染.js

import React, { useState } from "react";
import List from "./List";

const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => {
    if(number === ""){                     // changes
      return;
    }
    return [number, number + 5, number + 10];
  };

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => {
          if (e.target.value !== "") {               //changes
            setNumber(parseInt(e.target.value, 10));
          } else {
            setNumber(""); 
          }
        }}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

export default ReRendering;


0
投票

我认为发生这种情况是因为空输入的值是一个空字符串,

parseInt
不知道如何处理,因此返回
NaN
。 我认为您需要创建一个函数来处理该问题,并在输入的值为空字符串时将状态设置为 0。比如:

const handleChange = (e) => {
  const value = e.target.value;
  setNumber(value === '' ? 0 : Number(value));
}

此外,我认为我应该让您知道,您不需要

useState
组件中的
useEffect
<List />
。无论如何,当道具发生变化时,您的列表都会更新,因此您可以像这样进行映射:
getList().map(...rset of the code)


0
投票

我相信@CertainPerformance已经回答了你的-

让我知道我在这里做错了什么。

特别查看您关于输入字段中的

0
零问题的评论,我认为您可以通过数字检查来修改您的
getList()
方法,并在数字为空白时传递空白数组。

改变你的

getList()
方法 -

const getList = () => number ? [number, number + 5, number + 10] : [];
© www.soinside.com 2019 - 2024. All rights reserved.