【问题标题】:Migrating a React class component's state to a functional component将 React 类组件的状态迁移到功能组件
【发布时间】:2020-09-27 17:13:52
【问题描述】:

我正在使用 React 中的 Algolia,参考以下示例:

https://codesandbox.io/s/github/algolia/doc-code-samples/tree/master/React%20InstantSearch/routing-basic?file=/src/App.js

对于我的项目,虽然我使用的是功能组件。我试图弄清楚如何将 App 组件用作功能组件,但在弄清楚这部分代码时遇到了一些麻烦:

  state = {
    searchState: urlToSearchState(this.props.location),
    lastLocation: this.props.location,
  };

  static getDerivedStateFromProps(props, state) {
    if (props.location !== state.lastLocation) {
      return {
        searchState: urlToSearchState(props.location),
        lastLocation: props.location,
      };
    }

    return null;
  }

  onSearchStateChange = searchState => {
    clearTimeout(this.debouncedSetState);

    this.debouncedSetState = setTimeout(() => {
      this.props.history.push(
        searchStateToUrl(this.props, searchState),
        searchState
      );
    }, DEBOUNCE_TIME);

    this.setState({ searchState });
  };

我之前在函数式组件中处理过状态,但这看起来让我有些困惑。有没有办法把它写成一个功能组件,特别是上面代码中的状态?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    我将把你的代码分成 3 段,并尝试展示如何将每段代码转换为功能代码。

    #1第一部分是设置你的初始状态

      state = {
        searchState: urlToSearchState(this.props.location),
        lastLocation: this.props.location,
      };
    

      const [state , setState] = useState({
        searchState: urlToSearchState(props.location),
        lastLocation: props.location,
      }) 
    
    

    #2 第二反应 props.location 值的变化

      static getDerivedStateFromProps(props, state) {
        if (props.location !== state.lastLocation) {
          return {
            searchState: urlToSearchState(props.location),
            lastLocation: props.location,
          };
        }
        return null;
      }
    

      useEffect( () => {
         setState({
            searchState: urlToSearchState(props.location),
            lastLocation: props.location,
          })
      } , [ props.location ]) 
    
    

    #3 第三反应 searchState 值的变化

      onSearchStateChange = searchState => {
        clearTimeout(this.debouncedSetState);
    
        this.debouncedSetState = setTimeout(() => {
          this.props.history.push(
            searchStateToUrl(this.props, searchState),
            searchState
          );
        }, DEBOUNCE_TIME);
        this.setState({ searchState });
      };
    

      useEffect ( () => {
        clearTimeout(this.debouncedSetState);
        //handle debounce state at your own
        props.history.push(
            searchStateToUrl(props, searchState),
            searchState
        );
        setState({ ...state , searchState })
      } ,[])
    
    
    

    【讨论】:

    • 不错的答案。您可能要提到useEffect 的输入数组是强制性的(即使它是一个空数组[ ]),并且useEffect() 将在任何这些输入变量发生变化时重新运行。不过解释得很好 - 请回答更多问题!.
    • 谢谢您,非常感谢您的回答。你介意看看这个错误:codesandbox.io/s/late-http-q9nel?file=/src/App.js - 我不知道为什么我得到“未定义不是一个对象(评估'undefined.state')”
    【解决方案2】:

    试试这样的:

     const DEBOUNCE_TIME = 1000; // test, not in question's context
     const searchStateToUrl = (props, search) => console.log(search); // test, not in question's context
     const urlToSearchState = (loc) => console.log(loc); // test, not in question's context
    
     export default function AnsweredQuestion(props) {
       const { history, location } = props;
    
       const getSearchState = urlToSearchState(location);
       const [search, setSearch] = useState(getSearchState());
       const [lastLocation, setLastLocation] = useState(location);
       const [timerId, setTimerId] = useState(null);
    
       useEffect(() => {
         setSearch(getSearchState());
         setLastLocation(location);
       }, [location]); 
    
       const handleSearchStateChange = (updatedSearch) => {
         if (timerId) clearTimeout(timerId);
    
         const debounce = setTimeout(() => {
           history.push(searhStateToUrl(props, updatedSearch));
         }, DEBOUNCE_TIME);
    
         setTimerId(debounce);
         setSearch(updatedSearch);
       };
    };
    

    在我看来,我喜欢将状态分成单独的变量。如果我有更多的状态需要管理,我可能会使用useReducer。这里最大的一点是timerId存储在状态中,因为我们想在搜索状态发生变化时清除计时器。另外,getDerviedStateFromPropsuseEffect 的同义词。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-16
      • 2021-01-30
      • 2020-03-21
      • 2021-01-04
      • 2016-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多