【问题标题】:How to set state in useEffect hook using React and Typescript?如何使用 React 和 Typescript 在 useEffect 挂钩中设置状态?
【发布时间】:2020-07-22 06:14:38
【问题描述】:

当用户在页面“/items/:itemId”中使用 React 和 Typescript 时,我想将右属性从 16px 更改为 40px。

下面是我的组件sn-p,

const root = () => {
    <PopupContextProvider>
        <App/>
    </PopupContextProvider>
}


export const PopupContextProvider = ({ children }: any) => {
    return (
        <popupContext.Provider value={context}>
            {children}
                {(condition1 || condition2) && (
                    <Popup onHide={dismiss} />
                )}
        </popupContext.Provider>
    );
}


export function Popup({ onHide }: Props) {
    return (
        <Dialog>
            <DialogBody>
                <span>Title</span>
                <Description/>
            </DialogBody>
            <Actions>
                <span>Hide</span>
            </Actions>
        </Dialog>
    );
}


const Dialog = styled.div`
    position: fixed;
    right: 16px;//want to change this to 40px if user is in page 
    "/items/:itemId"
    display: flex;
    flex-direction: column;
`;

我尝试了什么?

export function Popup({ onHide }: Props) {
    const location = useLocation();
    const [isView, setIsView] = React.useState(false);
    if (location.pathname === '/items/:itemId') {
        setIsView(true);
        //Here, it doesn't change to true.
        //How can I do the same in useEffect or something that updates
    }
    return (
        <Dialog isView={isView}>
            <DialogBody>
                <span>Title</span>
                <Description/>
            </DialogBody>
            <Actions>
                <span>Hide</span>
            </Actions>
        </Dialog>
    );
}


const Dialog = styled.div<isView?:boolean>`
    position: fixed;
    ${({ isView }) => isView && 'right:  40px;'}
    display: flex;
    flex-direction: column;
`;

即使用户在页面“/items/:itemId”中,我上面的代码也不会用右 40px 更新弹出窗口的位置。

我不确定出了什么问题。有人可以帮我弄这个吗?谢谢。

编辑:

我根据提供的答案之一进行了尝试。

export function Popup({ onHide }: Props) {
    const location = useLocation();
    const [isView, setIsView] = React.useState(false);
    React.useEffect(() => {
        const match = matchPath(
            location.pathname,
            '/items/:itemId'
        );
        if (match) { //it doesnt get it into this condition since match is 
            //null
            setIsScheduleView(true);
        }
    }, []);
    return (
        <Dialog isView={isView}>
            <DialogBody>
                <span>Title</span>
                <Description/>
            </DialogBody>
            <Actions>
                <span>Hide</span>
            </Actions>
        </Dialog>
    );
}

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    你可以使用 useEffect hook 来实现你想要的副作用。

    首先,您可以将“位置”变量作为依赖项之一放入 useEffect 挂钩中,如下所示。

    useEffect(() => {
    
    // do your if condition
    // set isView state as side effect
    
    },[location]);
    

    其次,我认为你的条件不正确。

    location.pathname 将不等于 '/items/:itemId',因为 :itemId 是一个动态参数。因此,您可以选择使用包含方法来检查它是否是您的 url,或者您可以添加一个包装器,该包装器首先解析为“/items”,然后解析为“/items/:itemId”。当路由进入包装器时,您可以进行样式设置。

    编辑:或者更好的是,您可以使用 react-router 的 matchPath api,正如@ludwiguer 提到的那样,也可以匹配您的路径。

    【讨论】:

      【解决方案2】:

      正如@Kevin Moe Myint Myat 在他的回答中所解释的那样。您的条件不正确,因为其中包含动态 id。所以你可以使用includes方法检查/items,如果this.props.match可用,那么你可以使用它来检查param itemId是否存在。与 this.props.match.params.itemId 一样,您可以在 useEffect 中使用 AND &amp; 运算符将其与先前的条件一起使用。

      【讨论】:

        【解决方案3】:

        我想你正在使用 react 路由器,如果是这样你可以使用 matchPath https://reactrouter.com/web/api/matchPath

        import { matchPath } from 'react-router';
        
        setIsView(
         !!matchPath(
            this.props.location.pathname, 
            {path: 'items/:itemId'}
          )); 
        
        

        【讨论】:

        • 谢谢。但这给了我一个错误 Uncaught Invariant Violation: Too many re-renders。 React 限制渲染次数以防止无限循环
        • 我已经在使用效果中使用了它,就像在我编辑的问题中一样,但状态 isView 仍然是 false。
        • 我在 useeffect 中记录了匹配,我没有看到它在日志中打印,除非只有一次在弹出窗口安装并且最初位于其他 url 时。
        • 我用最新的 matchPath 实现更新了我的答案,你也可以在这里查看文档reactrouter.com/web/api/matchPath
        猜你喜欢
        • 2021-02-11
        • 2020-05-23
        • 2021-05-24
        • 2021-11-11
        • 2022-01-21
        • 2019-05-07
        • 2020-04-05
        • 2021-03-30
        • 2021-03-16
        相关资源
        最近更新 更多