如何使用React和Typescript在useEffect挂钩中设置状态?

时间:2020-07-21 02:19:06

标签: reactjs typescript

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

下面是我的代码段

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

3 个答案:

答案 0 :(得分:1)

我想您正在使用React Router,如果可以的话,您可以使用matchPath https://reactrouter.com/web/api/matchPath

import { matchPath } from 'react-router';

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

答案 1 :(得分:1)

正如@Kevin Moe Myint Myat在回答中所解释的。您的条件不正确,因为其中包含动态ID。因此,您可以使用include方法检查/items,如果this.props.match可用,则可以使用它来检查参数itemId是否存在。像this.props.match.params.itemId一样,您可以在useEffect中使用AND &运算符将其与以前的条件一起使用。

答案 2 :(得分:0)

您可以使用useEffect挂钩来实现所需的副作用。

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

useEffect(() => {

// do your if condition
// set isView state as side effect

},[location]);

第二,我相信您的情况不正确。

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

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