如何在React Native中从另一个函数中更改显示

huangapple go评论69阅读模式
英文:

How to change display from another function in react native

问题

我有一个在React Native中的类似这样的东西:

function HomeScreen({navigation}) {
    function startGenerate(exercises) {
        console.log(exercises);
        return (
            <View style={global.container}>
                <Button 
                    title="Generate recommended exercises"
                    onPress={() => navigation.navigate('List', {exercises: exercises})}
                />
            </View>
        )
    }

    var exercises = [];

    if (severityValue >= 7) {
        return (
            <View style={global.container}>
                <Text>Test</Text>
            </View>
        )
    } else if (severityValue != null) {
        writePainProfile(areaValue, typeValue, severityValue);
        onValue(ref(db, 'count'), (snapshot) => {
            const count = snapshot.val();
            exercises = filter(count);
            return (startGenerate(exercises));
        })
        // 在这里调用exercises会返回一个空数组
    }
    // ...为简洁起见,这里省略了其他代码
}

export default HomeScreen

通过onValue,我正在读取Firebase实时数据库,然后调用filter函数,该函数返回符合指定条件的数据列表。然后,我想通过startGenerate函数创建一个显示筛选数据的页面,但似乎没有任何内容渲染出来。所以,有没有更好的方法来实现这个?

我还注意到,在onValue之外尝试使用exercises会返回一个空数组,可能是由于onValue的工作方式,这显著复杂化了事情。

编辑:
这是exercises数组的格式,作为对象数组:

如何在React Native中从另一个函数中更改显示

这是我尝试渲染exercises数组元素的方式:

return (
    <View style={global.container}>
        {exercises.map(exercise => {
            return <Text>----</Text>;
        })}
    </View>
);
英文:

I have something in react native like this:

function HomeScreen({navigation}) {
    function startGenerate(exercises) {
        console.log(exercises);
            return (
                &lt;View style = {global.container}&gt;
                    &lt;Button 
                        title = &quot;Generate recommended exercises&quot;
                        onPress={() =&gt; navigation.navigate(&#39;List&#39;, {exercises: exercises})}
                    /&gt;
                &lt;/View&gt;
            )
    }
   

    var exercises = [];

    if (severityValue &gt;= 7) {
        return (
            &lt;View style = {global.container}&gt;
                &lt;Text&gt;Test&lt;/Text&gt;
            &lt;/View&gt;
        )
    } else if (severityValue!=null) {
        writePainProfile(areaValue, typeValue, severityValue);
        onValue(ref(db, &#39;count&#39;), (snapshot) =&gt; {
            const count = snapshot.val();
            exercises = filter(count);
            return (startGenerate(exercises));
        })
        //Calling exercises here returns an empty array
    } 
//...other code omitted here for brevity

}

export default HomeScreen

With the onValue, I'm reading a firebase realtime database, and then calling the filter function, which returns a list of filtered data that fit the specified criteria. I then want to create a page that displays the filtered data and I've attempted to do this through the startGenerate function, however nothing appears to be rendering. So, is there any better way to do this?

I've also noticed that attempting to use exercises outside the onValue returns an empty array, likely due to the way the onValue works, which significantly complicates things.

Edit:
Here's how the exercises array is formatted, as an Array of objects
如何在React Native中从另一个函数中更改显示

And here's how I am attempting to render elements of the exercises array:

return (
        &lt;View style={global.container}&gt;
        {exercises.map(exercise =&gt; {
            return &lt;Text&gt;----&lt;/Text&gt;
        })};
        &lt;/View&gt;
);

答案1

得分: 1

无法看到代码,但我理解您的问题是关于React中状态更新的问题。在React中,直接更新本地变量不会触发重新渲染,因为React不会自动侦测这种变化。您需要使用useStateuseEffect来管理状态,以便在数据发生更改时触发重新渲染。以下是您提供的示例的中文翻译:

import React from 'react';
import { View, Text, Button } from 'react-native';

function HomeScreen({ navigation }) {
  const [exercises, setExercises] = React.useState([]);
  
  React.useEffect(() => {
    // 这是在组件挂载时调用的
    writePainProfile(areaValue, typeValue, severityValue);
    onValue(ref(db, 'count'), (snapshot) => {
      const count = snapshot.val();
      // 更新状态
      setExercises(filter(count));
    });
  }, []);

  if (severityValue >= 7) {
    return (
      <View style={global.container}>
        <Text>测试</Text>
      </View>
    );
  }

  // 如果没有练习,显示占位符
  if (!(exercises?.length > 0)) {
    return (
      <View style={global.container}>
        <Text>加载中...</Text>
      </View>
    );
  }

  return (
    <View style={global.container}>
      <Button
        title="生成推荐的练习"
        onPress={() => navigation.navigate('List', { exercises: exercises })}
      />
      {exercises.map((exercise) => {
        return <Text>{exercise.name}</Text>;
      })}
    </View>
  );
}

export default HomeScreen;

如果您有关于React或代码的更多问题,请随时提出。

英文:

The reason why nothing is rendering is that updating a local variable var exercises = []; will not trigger a re-render in React. As onValue takes in a callback so it is async. We must update the state once the callback fires to trigger the re-render. Also please keep in mind that local variables are not permanent between re renders and functions called in a components body will fire on every render so you could end calling onValue more times than expected unless you use `useEffect. Instead, the way to achieve this would be to use React hooks to hold and set state. Please see example below:

import React from &#39;react&#39;;
import { View, Text, Button } from &#39;react-native&#39;;

function HomeScreen({ navigation }) {
  const [exercises, setExercises] = React.useState([]);
  // this is called on mount
  React.useEffect(() =&gt; {
    // running side effects
    writePainProfile(areaValue, typeValue, severityValue);
    onValue(ref(db, &#39;count&#39;), (snapshot) =&gt; {
      const count = snapshot.val();
      // update state
      setExercises(filter(count));
    });
  }, []);

  if (severityValue &gt;= 7) {
    return (
      &lt;View style={global.container}&gt;
        &lt;Text&gt;Test&lt;/Text&gt;
      &lt;/View&gt;
    );
  }
  // if no exercises yet display a placeholder
  if (!(exercises?.length &gt; 0)) {
    return (
      &lt;View style={global.container}&gt;
        &lt;Text&gt;Loading...&lt;/Text&gt;
      &lt;/View&gt;
    );
  }
  return (
    &lt;View style={global.container}&gt;
      &lt;Button
        title=&quot;Generate recommended exercises&quot;
        onPress={() =&gt; navigation.navigate(&#39;List&#39;, { exercises: exercises })}
      /&gt;
      // this should work for the provided format
     {exercises.map((exercise) =&gt; {
      return &lt;Text&gt;{exercise.name}&lt;/Text&gt;;
     })}
    &lt;/View&gt;
  );
}

export default HomeScreen;

huangapple
  • 本文由 发表于 2023年3月9日 15:22:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75681511.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定