【问题标题】:Redux and ReactJS Hooks: UseEffect Returns an Empty StateRedux 和 ReactJS Hooks:UseEffect 返回一个空状态
【发布时间】:2020-11-06 18:04:20
【问题描述】:

我有这个类组件,它返回使用 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>
  )
};

【问题讨论】:

  • @yousaf 它来自一个动作: import { fetchTopRatedMovies } from '../actions/topRatedAction.js';

标签: javascript reactjs redux react-hooks


【解决方案1】:

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

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

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

    要在功能组件中调度动作,请使用useDispatch()钩子并在组件挂载后使用useEffect钩子来调度此动作。

    import React, { useEffect } from "react";
    import { useDispatch } from "react-redux";
    
    const TopRatedComponent = () => {
       ...
       const dispatch = useDispatch();
    
       useEffect(() => {
           dispatch(fetchTopRatedMovies());
       }, []);
    
       ...
    };
    
  • 在类组件中,您使用this 访问props 对象,但在功能组件中,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 store 连接起来。

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

【讨论】:

    【解决方案2】:

    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>
      )
    };
    

    【讨论】:

    • 谢谢!这实际上有效,但是当我尝试访问 topRated 时仍然有效,因为那是我存储对象的位置 - 我已将 top rating 的状态初始化切换为 object {},但我仍然未定义。如果我直接访问状态,我会在控制台日志中注销我的东西...
    【解决方案3】:

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

    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>
        )
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-26
      • 2020-11-10
      • 1970-01-01
      • 2018-02-06
      • 2019-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多