Redux和ReactJS挂钩:UseEffect返回空状态

时间:2020-11-06 18:04:20

标签: javascript reactjs redux react-hooks

我有一个此类组件,该组件返回使用Redux商店完美填充的状态:

class TopRatedComponent extends Component {
    componentDidMount() {
        this.props.fetchTopRatedMovies();
    }
    render() {

        const IMG_API_ROOT_LINK = 'https://image.tmdb.org/t/p/w500';
        const { topRatedMovies, loading, error } = this.props;
        return (
            <div>
                {loading && <div>LOADING...</div>}
                {error && <div>{error}</div>}
                <Container className="p-4" onScroll={this.onScroll}>

                    <div className="text-center">

                        {
                            topRatedMovies.results && topRatedMovies.results.map(topRated => (
                                <p>{topRated.title}</p>
                            ))
                        }
                    </div>

                </Container>

            </div>
        );
    }
}




const mapStateToProps = state => {
    const { topRatedMovies, loading, error } = state.topRatedMovies;
    return {
        topRatedMovies,
        loading,
        error
    };
};

export default connect(
    mapStateToProps,
    {
        fetchTopRatedMovies
    }
)(TopRatedComponent);

但是,当我将上述类组件转换为下面的功能组件时,可以在代码中使用ReactJS钩子,但状态始终为空。

const TopRatedComponent = () => {
      const [count, setCount] = useState(0);
      const [topRated, settopRated] = useState([]);

      useEffect(() => {
        settopRated(this.props.fetchTopRatedMovies)
     }, [this.props.fetchTopRatedMovies])
     
    
  const allState = useSelector((state) => state)
  console.log('CHOF: ' + JSON.stringify(allState));
  return (
    <div>
     WOOOOOOOW....
    </div>
  )
};

3 个答案:

答案 0 :(得分:1)

this在功能组件中的工作方式不同。您需要从函数参数中拉取道具。

const TopRatedComponent = (props) => {
      const [count, setCount] = useState(0);
      const [topRated, settopRated] = useState([]);

      useEffect(() => {
        settopRated(props.fetchTopRatedMovies)
     }, [props.fetchTopRatedMovies])
     
    
  const allState = useSelector((state) => state)
  console.log('CHOF: ' + JSON.stringify(allState));
  return (
    <div>
     WOOOOOOOW....
    </div>
  )
};

答案 1 :(得分:1)

您没有正确地将基于类的组件转换为等效的功能组件。

以下是您的功能组件中的问题:

  • 在类组件中,您将收到fetchTopRatedMovies操作创建者作为道具,并从componentDidMount生命周期方法中将其分派。在功能组件中,您没有在分派它。

    要在功能组件中分派动作,请使用useDispatch()钩子,并使用useEffect钩子在组件安装后分派此动作。

    import React, { useEffect } from "react";
    import { useDispatch } from "react-redux";
    
    const TopRatedComponent = () => {
       ...
       const dispatch = useDispatch();
    
       useEffect(() => {
           dispatch(fetchTopRatedMovies());
       }, []);
    
       ...
    };
    
  • 在类组件中,您使用props访问this对象,但是在功能组件中,props对象作为参数传递。因此,您可以使用用于props对象的参数名称直接访问它

    const TopRatedComponent = (props) => {
       console.log(props);
       // code
    };
    
  • 使用mapStateToProps函数和connect高阶组件,组件可以从redux存储接收作为道具的数据,可以使用功能组件中的useSelector钩子来访问。

  • import { useSelector } from "react-redux";
    
    const TopRatedComponent = () => {
        const { 
           topRatedMovies,
           loading,
           error
        } = useSelector(state => state.topRatedMovies);
    
        // code
    };
    

    注意:您还可以使用connect高阶组件和mapStateToProps将功能组件与redux存储连接。

有关如何在react-redux中使用钩子的详细信息,请参见:react-redux - Hooks

答案 2 :(得分:1)

箭头函数没有自己的上下文(this变量)。我假设fetchTopRatedMovies是一个动作(thunk),它从API提取数据并将其设置为全局状态。在这种情况下,您还需要使用Redux钩子获取该数据(如果您使用的版本支持该数据)。

const TopRatedComponent = ({ fetchTopRatedMovies }) => {
    const [count, setCount] = useState(0);

    // this is written according to your `mapStateToProps` function.
    const { topRatedMovies, loading, error } = useSelector(({topRatedMovies}) => topRatedMovies);

    useEffect(() => {
      fetchTopRatedMovies();
    }, [fetchTopRatedMovies])
    
    if (loading) return 'LOADING...';
    if (error) return <div>{error.message}</div>
     
    return (
      <div>
        etc...
      </div>
    )
};