在接收到更改其状态的新道具后,我无法重新渲染组件。我对React Native和使用钩子都是新手,所以请多多包涵。这是有问题的组件:
function AreaChart(timeScale) {
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const [areaChartJS, setAreaChartJS] = useState(chartJS.areaChart(width, timeScale.timeScale));
useEffect(() => {
console.log(timeScale.timeScale);
setAreaChartJS(chartJS.areaChart(width, timeScale.timeScale));
}, [areaChartJS, timeScale]);
return(
<View>
<WebView
originWhitelist={['*']}
useWebKit={true}
source={{ html: areaChartHtml }}
domStorageEnabled={true}
javaScriptEnabled={true}
style={styles.WebViewStyle}
injectedJavaScript={areaChartJS}
/>
<Text>{timeScale.timeScale}</Text>
</View>
);
}
这需要一些解释。我使用的是仅用于Web的图表库,因此必须在此处使用WebView进行渲染。 areaChartHtml和areaChartJS是HTML和JS代码,由于它们都是本地的,因此将注入到WebView中。这两个都是WebView解析和呈现的字符串。我在另一个名为chartJS的文件中包含了JS代码,在传递设备的宽度和timeScale时会调用该文件,以便根据这些变量动态呈现图表。
问题是,更改timeScale后,该组件不会重新渲染,而是继续使用在初始渲染期间从父组件传递的初始timeScale。在useEffect挂钩中,我记录了timeScale并获得了正确的值,但是即使使用新的timeScale属性通过setAreaChartJS函数更改状态,也不会触发重新渲染。 WebView下的<Text>
元素还显示了timeScale的正确实时值,甚至从外部chartJS文件记录时也显示了正确的值,但是新的JS代码并未注入到WebView中。 <Text>
使用新值进行更新的事实告诉我,组件正在被重新渲染,但是WebView并未从状态中提取新的areaChartJS。
当组件完全卸载并再次安装时,timeScale将被正确注册,并相应地呈现图表。在没有完全重新安装组件的情况下如何实现?
答案 0 :(得分:0)
我已经设法通过将ref
放在WebView上并在.reload()
中调用其useEffect
方法来获得所需的行为。我不知道WebView的内部工作原理,但是我假设它会将注入的JS的初始值保存在某个地方,即使正在重新渲染组件,也不会注入新的值,除非您以这种方式强制重新加载。该组件现在的外观如下:
function AreaChart(timeScale) {
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
const [areaChartJS, setAreaChartJS] = useState(chartJS.areaChart(width, timeScale.timeScale));
const [currTimeScale, setCurrTimeScale] = useState('1h');
useEffect(() => {
setAreaChartJS(chartJS.areaChart(width, timeScale.timeScale));
if (currTimeScale !== timeScale.timeScale) {
WebViewRef.reload();
setCurrTimeScale(timeScale.timeScale);
}
}, [timeScale]);
return(
<View style={{flex: 1, height: 300}}>
<WebView
ref={WVref => (WebViewRef = WVref)}
originWhitelist={['*']}
useWebKit={true}
source={{ html: areaChartHtml }}
domStorageEnabled={true}
javaScriptEnabled={true}
style={styles.WebViewStyle}
injectedJavaScript={areaChartJS}
/>
</View>
);
}