Reactjs useState挂钩始终落后1步

Reactjs useState挂钩始终落后1步,reactjs,Reactjs,我见过其他标题完全相同的问题,但没有一个能解决我的问题: 这是我的代码: import React, { useState } from 'react'; import Validation from './Validation/Validation'; import Char from './Char/Char'; function App() { const [textState, textSetState] = useState(''); const [charsState, c

我见过其他标题完全相同的问题,但没有一个能解决我的问题: 这是我的代码:

import React, { useState } from 'react';
import Validation from './Validation/Validation';
import Char from './Char/Char';

function App() {
  const [textState, textSetState] = useState('');
  const [charsState, charsSetState] = useState([]);

  let inputChange = (event) => {
    textSetState(event.target.value);
    charsSetState(event.target.value.split('').map((char, index) => {
      return <Char char={char} key={index} click={() => { deleteCharHandler(index) }} />
    }));
  }

  const deleteCharHandler = (index) => {
    alert(textState);
  }
  return (
    <div className="App">
      <input type="text" onChange={(event) => inputChange(event)} />
      <Validation text={textState} />
      {charsState}
    </div>
  );
}

export default App;
import React,{useState}来自“React”;
从“./Validation/Validation”导入验证;
从“./Char/Char”导入字符;
函数App(){
常量[textState,textSetState]=使用状态(“”);
常量[charsState,charsSetState]=useState([]);
让inputChange=(事件)=>{
textSetState(event.target.value);
charsSetState(event.target.value.split(“”).map((char,index)=>{
返回{deleteCharHandler(index)}}/>
}));
}
常量deleteCharHandler=(索引)=>{
警报(文本状态);
}
返回(
输入更改(事件)}/>
{charsState}
);
}
导出默认应用程序;
结果是:


当我单击一个字符时,它会显示后面1步的值,如上面的示例。

我认为您需要
useCallback
或在参数中传递textState。
deleteCharHandler
方法不会随textState值的变化而及时更改

尝试:


因此,有一些事情可能会导致问题,也可能不会导致问题,所以让我们澄清一些事情:

  • 您不需要在输入上传递匿名函数:

    就足够了

  • 与OG state一样,同时调用两个setstate从来都不是一个好主意,因此让我们结合这两个:

    const[state,setState]=useState({text:'',char:[]})

  • 一旦更新了所有内容,就应该在单击时设置一个状态对象

  • 您的Char对象正在使用click而不是onClick?除非您将其用作回调方法,否则我将切换到:

    返回deleteCharHandler(索引)}/>


  • 如果这不能解决最后的问题,您只需将更新后的文本值传递给
    deleteCharHandler
    ,而不是重新获取状态值您正在将渲染的
    Char
    组件数组放入您的状态,然后对其进行渲染。这种方法存在许多问题

  • 状态的本地副本(
    charsState
    )不会立即更新;相反,React将使用state的新值重新渲染组件
  • 由于在函数中定义
    onClick
    回调,
    deleteCharHandler
    将始终引用状态的过期副本
  • 以这种方式更新lockstep中的多个状态挂钩将导致额外的重新渲染
  • 由于您的示例中的命名有点混乱,因此很难判断所需的行为是什么,以便为如何解决或重构提供良好的建议。

    试试这个

    function App() {
        const [textState, textSetState] = useState('');
    
        const inputChange = useCallback((event) => {
            textSetState(event.target.value);
        },[])
    
        function renderChars(){
            return textState.split('').map((char, index) => {
                return <Char char={char} key={index} click={() => { deleteCharHandler(index) }} />
            }));
        }
    
        const deleteCharHandler = useCallback( (index) => {
             alert(textState);
        }, [textState])
    
        return (
            <div className="App">
                <input type="text" onChange={inputChange} />
                <Validation text={textState} />
               {renderChars()}
           </div>
       );
    }
    
    函数应用程序(){
    常量[textState,textSetState]=使用状态(“”);
    常量inputChange=useCallback((事件)=>{
    textSetState(event.target.value);
    },[])
    函数rendercars(){
    返回textState.split(“”).map((字符,索引)=>{
    返回{deleteCharHandler(index)}}/>
    }));
    }
    const deleteCharHandler=useCallback((索引)=>{
    警报(文本状态);
    },[textState])
    返回(
    {rendercars()}
    );
    }
    
    这是否回答了您的问题?React state是异步的当您alert@BrianOgden你好否,因为我需要在单击某个字符时将其删除,因此在我更改状态时添加回调不会起作用。当您更新文本时,组件将重新渲染,然后只需映射JSX中的文本并渲染
    Char
    组件即可。当您想要删除字符时,只需更新文本statesure,因为对于基于类的组件,您正在通过引用访问最新的
    状态
    。而在功能组件中,您通常面临闭包(闭包中的过时数据是您面临上述问题的原因)1。我将如何访问输入的值?2.我要试试看。我在组件上使用onClick,我通过prop传递函数。单击onClick事件将自动通过事件对象,因为您不会更改它。不用担心!很高兴能帮上忙,不过后来又有人进来了,回答与XD rip差不多
    
    import React, { useState, useCallback } from 'react';
    ...
    const deleteCharHandler = useCallback(
      (index) => {
        alert(textState);
      }, [textState]);
    
    function App() {
        const [textState, textSetState] = useState('');
    
        const inputChange = useCallback((event) => {
            textSetState(event.target.value);
        },[])
    
        function renderChars(){
            return textState.split('').map((char, index) => {
                return <Char char={char} key={index} click={() => { deleteCharHandler(index) }} />
            }));
        }
    
        const deleteCharHandler = useCallback( (index) => {
             alert(textState);
        }, [textState])
    
        return (
            <div className="App">
                <input type="text" onChange={inputChange} />
                <Validation text={textState} />
               {renderChars()}
           </div>
       );
    }