Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.6k views
in Technique[技术] by (71.8m points)

关于react hooks的一些疑问

let number = 1;

const callback = () => {
  console.log('callback', number);
};

class Scroll {
  constructor(callback) {
    this.callback = callback;
  }
}

const scroll = new Scroll(() => console.log(number));

number = 2;

scroll.callback();

demo链接:http://js.jirengu.com/xeninan...
这种情况打印的是2,跟预期是一样的

import React from "react";
import ReactDOM from "react-dom";

class Scroller {
  constructor(callback) {
    console.log("hehe");
    this.callBack = callback;
  }

  doSomething() {
    this.callBack();
  }
}

const Demo = (props) => {
  const [scroller, setScroller] = React.useState(null);

  const onScrollerClick = () => {
    scroller.doSomething();
  };
  React.useEffect(() => {
    setScroller(
      new Scroller(() => {
        const { callback } = props;
        callback();
      })
    );
  }, []);
  return (
    <div>
      <button onClick={onScrollerClick}>scroller</button>
    </div>
  );
};

const Container = () => {
  const [count, setCount] = React.useState(1);
  const onCountClick = () => {
    setCount((preState) => {
      const newState = preState + 1;
      return newState;
    });
  };
  const callback = () => {
    console.log(count);
  };
  return (
    <div>
      <button onClick={onCountClick}>{count}</button>
      <Demo callback={callback} />
    </div>
  );
};

class App extends React.Component {
  render() {
    return <Container />;
  }
}

ReactDOM.render(<App />, document.getElementById("container"));

demo链接:https://codesandbox.io/s/reac...

先点击count改变count的值,再点击scroller打印count,发现每次打印的都是初始值。

求解答


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Demo组件里利用useRef保存变化的callback:

const Demo = (props) => {
  const { callback } = props;
  const [scroller, setScroller] = React.useState(null);
  const scrollerCallback = React.useRef(callback);

  const onScrollerClick = () => {
    scroller.doSomething();
  };

  React.useEffect(() => {
    scrollerCallback.current = callback;
  }, [callback])

  React.useEffect(() => {
    setScroller(
      new Scroller(() => {
        scrollerCallback.current()
      })
    );
  }, []);

  return (
    <div>
      <button onClick={onScrollerClick}>scroller</button>
    </div>
  );
};

还有一点:组件Demo里没必要使用state保存scroller值(因为看本Demo的用法更像是在使用成员变量):

const Demo = (props) => {
  const {callback} = props;
  const scroller = React.useRef(null);
  const scrollerCallback = React.useRef(callback);

  const onScrollerClick = () => {
    scroller.current.doSomething();
  };

  React.useEffect(() => {
    scrollerCallback.current = callback;
  }, [callback])

  React.useEffect(() => {
    scroller.current = 
      new Scroller(() => {
        scrollerCallback.current()
      })    
  }, []);

  return (
    <div>
      <button onClick={onScrollerClick}>scroller</button>
    </div>
  );
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...