【问题标题】:Multiple changes in state are not altering the screen状态的多次更改不会改变屏幕
【发布时间】:2021-12-17 14:33:35
【问题描述】:

(对不起,我的英语,我使用谷歌翻译)在我的代码中,我有几个迭代,在每个迭代中,我都会更改要在屏幕上显示的文本:

export function MyScreen() {
  const [currentText, setCurrentText] = useState('');
  async function sync() {
    setCurrentText('Sending configs') 
    await ConfigurationService.sync();
    setCurrentText('Sending clients')
    await ClientService.sync();
    setCurrentText('Fetching data for local sync')
    await api.get('http://myserver/get').then(async ({ data }) => {
        await syncClients(data);
        await syncProducts(data);
        //... call from other functions that also change setCurrentText
        setCurrentText('Sync finished');
        return true;
    })
    .catch(error => {
        setCurrentText('Sync failed');
        return false;
    });
  }

  async function syncClients(data) {
    setCurrentText('Sync local clients');
    // data.clients.new, data.clients.updated and data.clients.excluded is a long array
    if (data.clients) {
        if (data.clients.new) {
            setCurrentText(`Updating ${data.clients.new.length} clients`);
            for (let client of data.clients.new) {
                ClientRepository.save(client);
            }
        }
        if (data.clients.updated) {
            setCurrentText(`Updating ${data.clients.updated.length} clients`);
            for (let client of data.clients.updated) {
                ClientRepository.save(client );
            }
        }
        if (data.clients.excluded) {
            setCurrentText(`Excluding ${data.clients.excluded.length} clients`);
            for (let client of data.clients.excluded) {
                ClientRepository.delete(client);
            }
        }
    }
  }
  async function syncProducts(data) {
    setCurrentText('Sync local products');
    // data.products.new, data.products.updated and data.products.excluded is a long array
    if (data.products) {
        if (data.products.new) {
            setCurrentText(`Saving ${data.products.new.length} products`);
            for (let product of data.products.new) {
                ProductRepository.save(product);
            }
        }
        if (data.products.updated) {
            setCurrentText(`Updating ${data.products.updated.length} products`);
            for (let product of data.products.updated) {
                ProductRepository.save(product);
            }
        }
        if (data.products.excluded) {
            setCurrentText(`Excluding ${data.products.excluded.length} products`);
            for (let product of data.products.excluded) {
                ProductRepository.delete(product);
            }
        }
    }
  }
  return (
    <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
      <TouchableOpacity onPress={sync}>
        <Text>PRESS TO SYNC</Text>
      </TouchableOpacity>
      <Text>{currentText}</Text>
    </View
  );
}

事实证明 currentText 变量只更新了前 3 次,然后它已经更新了最后一个文本“同步完成”。在其他功能中触发的更新不会更新屏幕。 有没有人经历过这种情况?

【问题讨论】:

    标签: reactjs react-native react-hooks


    【解决方案1】:

    发生这种情况的原因是syncClientssyncProducts 函数不是异步的。 React 会在一个同步循环中获取所有已完成的状态更改,并获取最新的输出。

    示例:

    const [text, setText] = useState('');
    
    useEffect(() => {
    setText('first line');
    setText('second line');
    }, []);
    

    这会将text 值设置为“第二行”,因为这是使用setText 函数设置的循环中的最后一个值。

    const [text, setText] = useState('');
    
    useEffect(async () => {
    setText('first line');
    await delay(1000);
    setText('second line');
    }, []);
    

    由于这是异步的,它会首先将文本设置为“第一行”并渲染它。延迟后,它会将文本设置为“第二行”。

    【讨论】:

    • 即使使用异步它也不起作用。仅在最后一组中更新的文本...更新了我的问题
    • 这是因为即使你让它异步,它也没有等待任何东西。您希望将文本设置为这些值之间的原因是什么?数据将在几毫秒内得到处理,这意味着用户永远不会看到它。
    • 文本更改不会在毫秒内发生,因为每个函数需要超过 20 秒才能执行,因为我所做的操作是在 Realm 中,当列表很大时它们需要一定的时间,因为它是就我而言
    猜你喜欢
    • 1970-01-01
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 2015-05-16
    • 2020-06-08
    • 2023-03-04
    • 2018-08-06
    • 1970-01-01
    相关资源
    最近更新 更多