打字稿React useEffect Deps问题

时间:2020-03-10 09:16:01

标签: reactjs typescript

我正在将React与TypeScript一起使用,并且想利用SELECT category, sum(sales_volume), sum(return_volume), sum(return_volume) / sum(sales_volume) as return_rate FROM sales GROUP BY 1; 钩子。

我想做这样的事情

  1. 创建第一个useEffect来监听一些可观察到的rxJ,这将为我的组件设置内部状态的一个特定属性(此位起作用)

  2. 然后,我想听听组件内部状态变化的特定属性,当其变化时,我想在第二个useEffect中做点什么(这很可能称为redux派生操作)

这是初始状态

useEffect

这部分有效

const initialState = {
    isopen: false,
    selectedNodeText : ''
}

但是我想添加第二个const Home: React.FunctionComponent<HomeProps> = (props) => { const [currentState, setState] = useState(initialState); useEffect(() => { const sub = props.eventMessager.observe() .pipe( filter((event: IMessage) => event instanceof ShowInfoInSidePanel), map((event: IMessage) => event as ShowInfoInSidePanel) ) .subscribe(x => { setState({ ...currentState, isopen: true, selectedNodeText: x.itemClicked }); }); return () => { sub.unsubscribe(); } }, []); } ,我将状态的特定属性传递给我,所以这就是我所拥有的

useEffect

但是我收到此错误

enter image description here

但是所有将useEffect(() => { //TODO : make a async redux thunk call to get the data }, [currentState.selectedNodeText]); 与TypeScript一起使用的示例都可以满足我的要求。我该怎么做才能将useEffect转换为string[],以使ReadOnlyArray<any>开心?

2 个答案:

答案 0 :(得分:0)

好的,这可能是一个虚拟的示例,但是这里的想法是,仅当currentState.selectedNodeText更改时,才获得console.log输出,而状态的其他部分更改时,则不会获得:

import * as React from "react";
import "./styles.css";

interface IState {
  isopen: boolean;
  selectedNodeText: string;
}

const initialState: IState = {
  isopen: false,
  selectedNodeText: ""
};

interface CardProps {
  Title: string;
  Image: string;
  Body: string;
}

export const Card: React.FC<CardProps> = ({ Title }) => {
  const [currentState, setCurrentState] = React.useState<IState>(initialState);

  React.useEffect(() => {
    console.log("Changed");
  }, [currentState.selectedNodeText]);

  const handleClick = () => {
    setCurrentState({
      ...currentState,
      isopen: true,
      selectedNodeText: `${Math.random()}`
    });
  };

  const handleChangeIsOpen = () => {
    setCurrentState(prev => ({
      ...prev,
      isopen: !prev.isopen
    }));
  };

  return (
    <div className="card">
      <div className="title">{Title}</div>
      <div className="body">{`IsOpen ${currentState.isopen} with text ${
        currentState.selectedNodeText
      }`}</div>
      <button onClick={handleClick}>Change Selected Node Text</button>
      <button onClick={handleChangeIsOpen}>Change isOpen</button>
    </div>
  );
};

export default function App() {
  return (
    <div className="App">
      <Card Title="CardTitle" Image="Image" Body="Body" />
    </div>
  );
}

您可以在这里尝试:https://codesandbox.io/s/great-sea-26qcy

答案 1 :(得分:0)

您的结果中有一个依赖问题,不确定打字稿是否会注意到,但带有react-hooks的附加功能会告诉您有关情况。您可以尝试将回调传递给状态设置器,以便currentState不是依赖项。

道具。 eventMessager仍将是一个依赖项,因此请确保在父级重新渲染时不要更改此传递的prop的引用,因为如果这样做,它将每次都取消订阅和订阅。

const Home: React.FunctionComponent<HomeProps> = (props) => {

  const [currentState, setState] = useState(initialState);

  useEffect(() => {
      const sub = props.eventMessager.observe()
      .pipe(
          filter((event: IMessage) => event instanceof ShowInfoInSidePanel),
          map((event: IMessage) => event as ShowInfoInSidePanel)
      )
      .subscribe(x => {
          //pass callback to setState to prevent currentState
          //  being a dependency
          setState(
            (currentState)=>({ 
              ...currentState,
              isopen: true,
              selectedNodeText: x.itemClicked
            })
          );
      });

      return () => {
          sub.unsubscribe();
      }
  }, [props.eventMessager]); //add props.eventMessager as dependency
}

您收到的另一个错误可能是因为传入了您没有使用的依赖项,请尝试以下操作:

useEffect(
  () => console.log(currentState.selectedNodeText),//using the dependency
  [currentState.selectedNodeText]
);