[英]React Native - useEffect will render Home twice
我想在“useEffect”中从 function 获取数据后渲染我的功能组件“Home”,但是当我在我的 const 中设置来自 function 的数据时,我的 Home 组件将再次渲染。
如果我删除“set”语句,它只会呈现一次。
当 HomeSrceen 第二次渲染时,它将启动一个位于子组件中的导航语句。
谁能解释我为什么会发生这种情况以及我如何解决这个问题?
我的代码:HomeScreen.js
export function HomeScreen( navigation ) {
const [item, setItem] = React.useState([]);
console.log('fire home')
React.useEffect(() => {
getbannerdata()
.then(res => setItem(res))
}, []);
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
<Banner data={item} navigation={navigation}/>
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
banneritem.js(将触发导航语句)
const BannerItem = ({ item, navigation }) => {
return (
<View style={styles.cardView} onTouchStart={navigation.navigation.navigate('Setting')}>
<Image style={styles.image} source={{uri: item.header}} />
<TouchableOpacity>
<View style={styles.textView}>
<Text style={styles.itemTitle}>{item.title}</Text>
<Text numberOfLines={2} style={styles.itemDescription}>{item.content}</Text>
</View>
</TouchableOpacity>
</View>
)
}
横幅数据.js
function getbannerdata(){
console.log('fire bannerdata')
return fetch ('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then((resData) => {
return resData;
})
.catch(error => console.log(error))
};
export { getbannerdata }
output端子
Finished building JavaScript bundle in 634ms.
Running application on Léons iPhone.
fire home
fire bannerdata
fire home
从 function 获取数据后,我想渲染我的功能组件“主页”...
然后你必须从父组件中的getbannerdata
中获取数据,并将其作为 props 传递给HomeScreen
。 您无法在HomeScreen
中执行任何操作来防止组件在来自getbannerdata
的数据到达之前呈现。
一般来说,对于组件,当有一个异步过程来获取它们的内容时,您有两种选择:
在组件中执行此操作,并处理呈现组件还没有数据的情况(可能带有“正在加载”消息或类似消息)。
在拥有数据之前不要创建组件,这意味着在父级中进行。
#1 的示例:
const { useState, useEffect } = React; function getbannerdata() { return new Promise(resolve => { setTimeout(resolve, 800, "This is the banner"); }); } const HomeScreen = () => { const [banner, setBanner] = useState(null); useEffect(() => { getbannerdata().then(banner => setBanner(banner)); }, [banner]); return ( <div className="boxed"> This is <code>HomeScreen</code> {banner && <div className="boxed">{banner}</div>} </div> ); }; const App = () => { return ( <div className="boxed"> This is <code>App</code> <HomeScreen /> </div> ); }; ReactDOM.render(<App />, document.getElementById("root"));
.boxed { border: 1px solid black; padding: 4px; }
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
或带有“加载”指示器:
const { useState, useEffect } = React; function getbannerdata() { return new Promise(resolve => { setTimeout(resolve, 800, "This is the banner"); }); } const HomeScreen = () => { const [banner, setBanner] = useState(null); useEffect(() => { getbannerdata().then(banner => setBanner(banner)); }, [banner]); return ( <div className="boxed"> This is <code>HomeScreen</code> <div className="boxed">{banner? banner: <em>Loading...</em>}</div> </div> ); }; const App = () => { return ( <div className="boxed"> This is <code>App</code> <HomeScreen /> </div> ); }; ReactDOM.render(<App />, document.getElementById("root"));
.boxed { border: 1px solid black; padding: 4px; }
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
#2 的例子:
const { useState, useEffect } = React; function getbannerdata() { return new Promise(resolve => { setTimeout(resolve, 800, "This is the banner"); }); } const HomeScreen = ({banner}) => { return ( <div className="boxed"> This is <code>HomeScreen</code> <div className="boxed">{banner}</div> </div> ); }; const App = () => { const [banner, setBanner] = useState(null); useEffect(() => { getbannerdata().then(banner => setBanner(banner)); }, [banner]); return ( <div className="boxed"> This is <code>App</code> {banner && <HomeScreen banner={banner} />} </div> ); }; ReactDOM.render(<App />, document.getElementById("root"));
.boxed { border: 1px solid black; padding: 4px; }
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
我发现 Dan Abramov 的这篇文章非常有用。 表面上它是关于useEffect
的,但实际上它是关于功能组件生命周期和一般钩子的。
TJ Crowder 是对的,也因为正在发生的事情是完全正常的。
您正在执行的操作流程是: - 实际触发 useEffect 之前的主页 - 触发 useEffect - 再次主页渲染,因为调用了 setItem
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.