1

I want to change right property from 16px to 40px when user is in page "/items/:itemId" using React and Typescript.

Below is my component snippet,

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;
`;

What I have tried?

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;
`;

My above code doesn't update the position of the popup with right 40px even though user is in page "/items/:itemId".

I am not sure what is going wrong. Can someone help me with this? Thanks.

EDIT:

what i have tried based on one of the answer provided.

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 Answers 3

1

You can use useEffect hook to implement the side effect that you want.

First, you can put "location" variable as one of the dependencies inside useEffect hook as below.

useEffect(() => {

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

},[location]);

Secondly, I believe your condition is not correct.

location.pathname will not equal to '/items/:itemId' since :itemId is a dynamic parameter. So, you have an option to use includes method to check if it is your url or you can add a wrapper which will resolve to "/items" first , then to "/items/:itemId". When the route comes into the wrapper, you can do the styling.

EDIT: or better yet you can use matchPath api of react-router as @ludwiguer has mentioned also to match your path.

Sign up to request clarification or add additional context in comments.

Comments

1

As explained by @Kevin Moe Myint Myat in his answer. Your condition is not correct as it contains a dynamic id in it. So you can check for /items using includes method and if this.props.match is available, then you can use it to check if param itemId is present or not. Like this.props.match.params.itemId, you can use this with previous condition with AND & operator in useEffect.

Comments

1

I imagine you are using react router, if so you can use matchPath https://reactrouter.com/web/api/matchPath

import { matchPath } from 'react-router';

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

4 Comments

thanks. but this gives me an error Uncaught Invariant Violation: Too many re-renders. React limits the number of renders to prevent an infinite loop
i have used it in useeffect like in my edited question and still the state isView is false.
i was logging match in useeffect and i dont see it printed in log except only once when popup is mounted and is in other url initially.
I updated my answer with the most recent implementation of matchPath, also you can check the docs here reactrouter.com/web/api/matchPath

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.