Javascript 在react hook中获取时没有正确的数据

Javascript 在react hook中获取时没有正确的数据,javascript,reactjs,react-hooks,use-effect,Javascript,Reactjs,React Hooks,Use Effect,下面的代码在初始加载时运行良好,但单击“获取数据”按钮后,现在可以正确获取数据。让我知道我做错了什么 代码- const Sample = () => { const [todoCount, setTodoCount] = useState(3); const [todos, setTodos] = useState([]); useEffect(() => { Array(todoCount) .fill() .map((_x, i) =

下面的代码在初始加载时运行良好,但单击“获取数据”按钮后,现在可以正确获取数据。让我知道我做错了什么

代码-

const Sample = () => {
  const [todoCount, setTodoCount] = useState(3);
  const [todos, setTodos] = useState([]);
  useEffect(() => {
    Array(todoCount)
      .fill()
      .map((_x, i) => {
        return axios
          .get(`https://jsonplaceholder.typicode.com/todos/${i + 1}`)
          .then((res) => {
            const todo = res.data.title;
            setTodos((prevTodos) => {
              return [...prevTodos, todo];
            });
          });
      });
  }, [todoCount]);

  const fetchMore = (e) => {
    setTodoCount((prevCount) => prevCount + 1);
  };

  return (
    <div className="example">
      <h3>Fetch data in a loop</h3>
      <ul>
        {todos.map((x, i) => (
          <li key={i}>{x}</li>
        ))}
      </ul>

      <button onClick={fetchMore}>Fetch More</button>
    </div>
  );
};

export default Sample;
const Sample=()=>{
常量[todoCount,setTodoCount]=useState(3);
const[todos,setTodos]=useState([]);
useffect(()=>{
数组(todoCount)
.fill()
.map((x,i)=>{
返回轴
.得到(`https://jsonplaceholder.typicode.com/todos/${i+1}`)
。然后((res)=>{
const todo=res.data.title;
setTodos((prevTodos)=>{
返回[…上一个todo,todo];
});
});
});
},[todoCount]);
常量fetchMore=(e)=>{
setTodoCount((prevCount)=>prevCount+1);
};
返回(
在循环中获取数据
    {todos.map((x,i)=>(
  • {x}
  • ))}
多拿些 ); }; 导出默认样本;
代码沙盒-

预期结果-

  • 初始加载-3个标题
  • 单击“获取更多”按钮,将4添加到列表中,使其变为7,而应为4(仅增量1)

  • 您面临这种行为,因为一旦
    todoCount
    更新
    useffect
    就会再次运行。现在
    todoCount
    总共是4个,这样它将再获取4个todo(大多数将重复,因为只有最后一个
    i
    值应该会带来一个新值)

    根据您的代码,您可以在装载时中断初始计数获取,然后中断其他计数获取后续计数:

    const initialCount = 3
    const baseUrl = 'https://jsonplaceholder.typicode.com/todos'
    
    const Sample = () => {
      const [todoCount, setTodoCount] = useState(initialCount);
      const [todos, setTodos] = useState([]);
    
      useEffect(() => {
        Array(initialCount)
          .fill()
          .map((_x, i) => {
            return axios
              .get(`${baseUrl}/${i + 1}`)
              .then((res) => {
                const todo = res.data.title;
                setTodos((prevTodos) => {
                  return [...prevTodos, todo];
                });
              });
          });
      }, []);
    
      useEffect(() => {
        if (todoCount === initialCount) return
        axios
          .get(`${baseUrl}/${todoCount}`)
          .then((res) => {
            const todo = res.data.title;
              setTodos((prevTodos) => {
                return [...prevTodos, todo];
              });
           })
      }, [todoCount])
    
    虽然
    todoCount
    是从
    todos
    长度派生出来的,这是一种冗余状态,但您可以将其删除。之后,您可以只更改一个
    useffect
    ,并将fetch函数更改为使用
    todos.length
    作为参考:

    const initialCount = 3
    const baseUrl = 'https://jsonplaceholder.typicode.com/todos'
    
    const Sample = () => {
      const [todos, setTodos] = useState([]);
      useEffect(() => {
        Array(initialCount)
          .fill()
          .map((_x, i) => {
            return axios
              .get(`${baseUrl}/${i + 1}`)
              .then((res) => {
                const todo = res.data.title;
                setTodos((prevTodos) => {
                  return [...prevTodos, todo];
                });
              });
          });
      }, []);
    
      const fetchMore = (e) => {
        axios
          .get(`${baseUrl}/${todos.length + 1}`)
          .then((res) => {
             const todo = res.data.title;
             setTodos((prevTodos) => {
               return [...prevTodos, todo];
             });
           });
      };
    

    如果在map函数中运行
    setTodos
    ,则每次累积
    Todos
    时都会运行。您可以尝试以下方法:

    const Sample = () => {
      const [todoCount, setTodoCount] = useState(3);
      const [todos, setTodos] = useState([]);
      useEffect(() => {
        const todoArray = Array(todoCount)
          .fill()
          .map((_x, i) => {
            return axios
              .get(`https://jsonplaceholder.typicode.com/todos/${i + 1}`)
              .then((res) => {
                const todo = res.data.title;
                return todo;
              });
          });
        Promise.all(todoArray).then((todos) => {
          console.log(todos);
          setTodos(todos);
        });
      }, [todoCount]);
    

    立即设置todo也会使应用程序在每次fetchMore点击时只重新呈现一次,而不是在结果中的每个todo。

    谢谢你的回答,但你不认为这会在代码中造成重复吗?是的,你是对的,我会将axios逻辑抽象到某个函数中,并封装到useCallback中。我没有这样做,因为这不是问题的重点。谢谢你的良好做法:)+1这也解决了你的问题,你得到了你的预期结果,不是吗?