用redux将componentDidUpdate(prevProps)重写为一个钩子

时间:2020-03-29 01:42:52

标签: javascript reactjs react-redux

我想将此生命周期方法重写为一个钩子,但无法按预期工作。 挂载组件后,如果本地存储中存在用户ID,则表示该用户已连接,并且其名称显示在导航栏中。当他断开连接并重新连接时,他的名字将显示在导航栏中。 因此,我尝试使用钩子转换此类Component,当用户名更改时,导航栏中不显示任何内容,因此我必须刷新页面并以这种方式显示他的名字

真正的问题是componentDidUpdate 我如何获得和比较带有钩子的prevProps

类Component

const mapStateToProps = state => ({
        ...state.authReducer
    }
);
const mapDispatchToProps = {
    userSetId,
    userProfilFetch,
    userLogout
};

class App extends React.Component {

    componentDidMount() {
        const userId = window.localStorage.getItem("userId");
        const {userSetId} = this.props;
        if (userId) {
            userSetId(userId)
        }
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        const {userId, userProfilFetch, userData} = this.props; //from redux store
        if(prevProps.userId !== userId && userId !== null && userData === null){
            userProfilFetch(userId);

        }
    }
    render() {
    return (
        <div>
          <Router>
              <Routes/>
          </Router>
        </div>
    );
  }
}
export default connect(mapStateToProps,mapDispatchToProps)(App);

带钩子

const App = (props) => {
    const dispatch = useDispatch();
    const userData = useSelector(state => state.authReducer[props.userData]);
    const userId = window.localStorage.getItem("userId");


    useEffect(()=> {
        if(!userId){
            dispatch(userSetId(userId))
            dispatch(userProfilFetch(userId))
        }
    }, [userData, userId, dispatch])

    return(
        <Router>
            <Routes/>
        </Router>
    )
};

export default App;

2 个答案:

答案 0 :(得分:2)

How to get the previous props or state?

基本上创建一个自定义钩子来缓存值:

const usePrevious = value => {
  const ref = useRef();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

用法:

const App = (props) => {
  const dispatch = useDispatch();
  const userData = useSelector(state => state.authReducer[props.userData]);
  const userId = window.localStorage.getItem("userId");

  // get previous id and cache current id
  const prevUserId = usePrevious(userId);

  useEffect(()=> {
    if(!userId){
      dispatch(userSetId(userId))
      dispatch(userProfileFetch(userId))
    }

    // do comparison with previous and current id value
    if (prevUserId !== userId) {
      dispatch(userProfileFetch(userId));
    }
  }, [userData, userId, prevUserId, dispatch])

  return(
    <Router>
      <Routes/>
    </Router>
  )
};

FYI:您可能需要对代码进行一些重构,以便在仅在安装时运行的效果挂钩中进行从本地存储的提取。如果我正确了解您的应用程序流程,它将看起来像这样:

const App = (props) => {
  const dispatch = useDispatch();
  const { userId } = useSelector(state => state.authReducer[props.userData]);

  useEffect(() => {
    const userId = window.localStorage.getItem("userId");
    userId && dispatch(userSetId(userId));
  }, []);

  // get previous id and cache current id
  const prevUserId = usePrevious(userId);

  useEffect(()=> {
    if(!userId){
      dispatch(userSetId(userId))
      dispatch(userProfileFetch(userId))
    }

    // do comparison with previous and current id value
    if (prevUserId !== userId) {
      dispatch(userProfileFetch(userId));
    }
  }, [userId, prevUserId, dispatch])

  return(
    <Router>
      <Routes/>
    </Router>
  )
};

答案 1 :(得分:0)

现在我解决了,我做了


const App = props => {
    const userId = window.localStorage.getItem("userId");
    const dispatch = useDispatch();
    const userData = useSelector(state=> state.authReducer[props.userData]);
    const isAuthenticated = useSelector(state=> state.authReducer.isAuthenticated);

    useEffect(()=> {
        if(userId){
            dispatch(userSetId(userId))
            dispatch(userProfilFetch(userId))
        }
    }, [userId])
    return(
        <div>
            <Router>
                <Routes/>
            </Router>
        </div>
    )
};