React Native功能组件更新状态仅在第二次提交时

时间:2020-01-05 15:05:31

标签: reactjs react-native asynchronous react-hooks

当我控制台记录我的值时,仅当我第二次提交表单时它才会更新。为什么会这样?

const Link = (props) => {
  const { state, scrape } = useContext(ScrapeContext);
  const [clipboard, setClipboard] = useState();
  const [googleClip, setGoogleClip] = useState(false);
  const [googleLink, setGoogleLink] = useState('');

  const urlFromClipboard = () => {
    Clipboard.getString().then((content) => {
      if (content.includes('https://www.google.com')){
        setGoogleClip(true);
        console.log('googleLink', googleLink);
        setClipboard(content);
        setGoogleLink(`${content.split('?')[0]}?__a=1`);
      } else {
        setGoogleClip(false);
      }
    });

    if (googleClip) {
      console.log(googleLink);
      scrape({ googleLink });
    }
  }

  useEffect(() => {
    urlFromClipboard();
    console.log('useEffect googleLink', googleLink);
    console.log('useEffect state', state);
  }, [clipboard]);


  return (
    <View style={styles.container}>
      <View style={styles.inputFieldContainer}>
        <TextInput
          style={styles.inputField}
          placeholder='Enter Google url'
          autoCapitalize='none'
          autoCorrect={false}
          value={googleClip ? clipboard : ''}
        />
      </View>
      <View style={styles.buttonContainer}>
        <TouchableOpacity
          onPress={() => {
            urlFromClipboard();
          }}
          style={styles.touchSubmit}
        >
          <Text style={styles.touchText}>Submit</Text>
        </TouchableOpacity>
      </View>
      {state.errorMessage ? (
        <Text style={styles.errorMessage}>{state.errorMessage}</Text>
      ) : null}
    </View>
  );
}

我在这里拥有的一个组件将从URL中获取数据,并且在提交时会刮擦应用程序所需的某些信息,但是,如果我按下两次提交按钮,它只会更新那些控制台日志值。

3 个答案:

答案 0 :(得分:2)

这里的问题是,您在设置状态后无法立即访问该状态。因此,您实际上设置了状态,状态就在那里,但是您仅在第二次运行控制台日志时才看到更新后的状态。这并不意味着您必须提交两次,而是第二次提交时,第二次运行console.log并查看该值。由于设置状态函数是异步的,在这种情况下,您需要使用回调函数在控制台上实际查看更新后的状态。希望有帮助。

答案 1 :(得分:1)

就像提到Bora Sumer一样,您试图在实际更新状态值之前使用它们。您可以执行以下操作:

    Clipboard.getString().then((content) => {
      if (content.includes('https://www.google.com')){

        let link = `${content.split('?')[0]}?__a=1`
        setGoogleClip(true);
        console.log('googleLink', googleLink);
        setClipboard(content);
        setGoogleLink(link);
        console.log(link);
        scrape({ googleLink: link });

      } else {
        setGoogleClip(false);
      }
    });

答案 2 :(得分:0)

每次设置State时都可以使用async / await,如下所示:

const urlFromClipboard = () => {
Clipboard.getString().then( async (content) => {
  if (content.includes('https://www.google.com')){
    await setGoogleClip(true);
    console.log('googleLink', googleLink);
    await setClipboard(content);
    await setGoogleLink(`${content.split('?')[0]}?__a=1`);
  } else {
    await setGoogleClip(false);
  }
 });

 if (googleClip) {
    console.log(googleLink);
    scrape({ googleLink });
 }
}