亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

React use對函數道具的影響

React use對函數道具的影響

慕哥9229398 2022-08-27 13:39:51
剛剛開始使用 React 函數鉤子。我正在研究一個案例,其中你有一個傳遞數組的父函數和一個依賴于數組內容的子函數。應用.js(父級)->import React, {useEffect} from 'react';import ChartWrapper from './StaticChart/ChartWrapper';import './App.css';function App() {  let data = [];  function newVal() {    let obj = null;    let val = Math.floor(Math.random() * 10);    let timeNow = Date.now();    obj = {'time': timeNow, 'value': val};    data.push(obj);   // console.log(obj);  }  useEffect(    () => {      setInterval(() => {newVal();}, 500);    }, []  );  return (    <div className="App">      <ChartWrapper data={data} />    </div>  );}export default App;圖表包裝工.js(兒童)->import React, {useRef, useEffect} from 'react';export default function ChartWrapper(props) {    const svgRef = useRef();    const navRef = useRef();    useEffect(        () => {            console.log('function called');        }, [props.data]            );    return (        <div>            <svg ref = {svgRef} width = {700} height = {400}></svg>            <svg ref = {navRef} width = {700} height = {75}></svg>        </div>    );}因此,每次 App.js 在數組中添加新對象時,都會調用 ChartWrapper。目前,在ChartWrapper函數中,我使用了Effect,它應該監聽props.data數組中的更改并得到執行,但它不起作用。最初調用函數的唯一時間是組件呈現時。我做錯了什么?
查看完整描述

2 回答

?
呼喚遠方

TA貢獻1856條經驗 獲得超11個贊

好的,我運行了你的代碼并找出了問題所在。 正在更改,但它不會觸發 的重新渲染 。因此,您的 in 只運行一次(在初始渲染時)。要觸發重新渲染,您需要使用以下命令創建和更新:dataChartWrapperuseEffectChartWrapperdatauseState


let [data, setData] = useState([])


function newVal() {

    let obj = null;

    let val = Math.floor(Math.random() * 10);

    let timeNow = Date.now();

    obj = {'time': timeNow, 'value': val};

    const newData = [...data]

    newData.push(obj)

    setData(newData)

}

但是,這還不夠。由于您的函數定義了一次,因此其調用上下文中的值將始終是 的初始值(即空數組)。您可以通過在函數中執行此操作來查看這一點。要解決此問題,您也可以添加為依賴項:setIntervaldatadataconsole.log(data)newValdatauseEffect


useEffect(() => {

  setInterval(newVal, 1000);

}, [data]);

但是,每次數據更改時,您都會創建一個新的;你最終會同時運行其中的許多。您可以通過從中返回一個函數來清理setInterval:setIntervaluseEffectclearInterval


useEffect(() => {

  const interval = setInterval(newVal, 1000);


  return () => clearInterval(interval)

}, [data]);

但是在這一點上,你不妨改用:setTimeout


useEffect(() => {

  const timeout = setTimeout(newVal, 1000);

  return () => clearTimeout(timeout)

}, [data]);

這將導致每次更改時都會創建一個新的,因此它將像您的 .setTimeoutdatasetInterval


無論如何,你的代碼看起來像這樣:


const ChartWrapper = (props) => {

    useEffect(

        () => {

            console.log('function called');

        }, [props.data]        

    );


    return <p>asdf</p>

}


const App = () => {

  let [data, setData] = useState([])


  function newVal() {

    let obj = null;

    let val = Math.floor(Math.random() * 10);

    let timeNow = Date.now();

    obj = {'time': timeNow, 'value': val};

    const newData = [...data]

    newData.push(obj)

    setData(newData)

  }


  useEffect(() => {

    const timeout = setTimeout(newVal, 1000);

    return () => clearTimeout(timeout)

  }, [data]);


  return (

     <ChartWrapper data={data} />

  )

}

還有一個運行的例子:https://jsfiddle.net/kjypx0m7/3/


需要注意的是,這與 ChartWrapper 的依賴關系一樣運行良好。這是因為當被調用時,它總是被傳遞一個新的數組。因此,當 ChartWrapper 重新渲染時,實際上是不同的。useEffect[props.data]setDataprops.data


查看完整回答
反對 回復 2022-08-27
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

鉤子依賴關系中的對象通過引用進行比較。由于數組也是對象,因此當您說對數組的引用不會更改時,因此不會觸發鉤子。data.push

另一方面,基元值按值進行比較。由于 是 基元類型 (),因此出于您的目的,將依賴項放在上可以解決問題。data.lengthnumberdata.length

但是,如果不修改數組的長度,只修改數組中的值,則觸發引用差異的最簡單方法(如第一段中所述)是將此數組包裝在鉤子中。setState

下面是一個工作示例:https://codesandbox.io/s/xenodochial-murdock-qlto0。將子組件中的依賴項從 更改為 沒有區別。[data.length][data]


查看完整回答
反對 回復 2022-08-27
  • 2 回答
  • 0 關注
  • 139 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號