Open multiple pages with React Router Dom and Redux - javascript

I need to create a link which opens more than one route in a new tab when I click on the "Box" component. I'm using Redux
That's the template I'm following, but I'm stucked cause it seems it is not persisting state (which contains authentication datas) opening in a new tabs.
const onClickBox = () => {
onClickPageOne();
onClickPageTwo();
}
const onClickPageOne = () => {
dispatch(actions.fetchDataPageOne)
}
const onClickPageTwo = () => {
dispatch(actions.fetchDataPageTwo)
}
return (
<>
<Box
onClick = {onClickBox }
>
Click me!
</Box>
</>
)
I tried using Link component by react-router-dom but I need only one link for both pages so I don't know what to put in 'to' prop.
I tried using Redirect in onClickBox function but I don't get how to tell him to open in a new page.

You can use single function to dispatch bothh actions from there only

Related

Having an issue with making react component work inside a custom iframe component

So, I've basically tried everything with this one. I ran out of solutions or options. Thing is, I have a button. When you click on it your camera will open and you will see some filters that you can apply to your face. I am new to React. Made it work without the iframe to test the API first, but it's not working anymore inside this iframe. The react component needs to be inside this iframe. The code can be found here with what I did so far/tried: https://codesandbox.io/s/cool-fog-3k5si5?file=/src/components/button/button.jsx
The problem is that when I click the button, the canvas disappears from the page and I get this error in the console:
The DeepAR API fails initialization because the canvas is no longer on the page and it crashes. I really don't know what to search for as I considered this to be a react render error and I tried different ways to write the react code (functional/class). If you have any ideas or suggestions, please help. Thank you in advance.
Your use of useEffect in your Modal and App Component is incorrect.
To remind you, useEffect accepts a function which runs after the render is committed to the screen.
If the function returns a function (which is your case), this function is the "clean up" function which is run before the component is removed from the UI.
So what is happening is that your useEffect code is run only when your components are being unmounted.
Since we are not concerned with any clean up at this stage, a quick solution for you is to move the clean up expressions to the main effect function as follows:
useEffect(() => {
fetch(
"https://cors-anywhere.herokuapp.com/https://staging1.farmec.ro/rest/V1/farmec/deeparProducts/"
)
.then((response) => response.json())
.then((productsJson) => setProducts(productsJson));
}, []);
The same goes for your Modal component :
useEffect(() => {
let initializedDeepAR = new DeepAR({
licenseKey:
"6fda241c565744899d3ea574dc08a18ce3860d219aeb6de4b2d23437d7b6dcfcd79941dffe0e57f0",
libPath: DeepAR,
deeparWasmPath: deeparWasm,
canvas: canvas.current,
segmentationConfig: {
modelPath: segmentationMode
},
callbacks: {
onInitialize: () => {
// let filterName = colors[0].filterData[0]['Filter Binary Path'].match(new RegExp("[^/]+(?=\\.[^/.]*$)"))[0];
setDeepAR(initializedDeepAR);
initializedDeepAR.startVideo(true);
// initializedDeepAR.switchEffect(0, 'slot', `https://staging1.farmec.ro/media/deepArFilters/${filterName}.bin`);
}
}
});
/*#TODO: replace paths with server local path*/
initializedDeepAR.downloadFaceTrackingModel(models);
}, []);
With one additional fix concerning your use of useRef.
To target the element behind the useRef, you must use the .current property.
Finally, your Frame component is using useState to manage the mounting of the iframe. I would suggest using the useRef hook with a useState for your mountNode as follows:
export const Frame = ({
children,
styleSelector,
title,
...props
}) => {
const contentRef = useRef(null)
const [mountNode, setMountNode] = useState()
useEffect(() => {
setMountNode(contentRef.current.contentWindow.document.body)
}, [])
useEffect(() => {
const win = contentRef.current.contentWindow
const linkEls = win.parent.document.querySelectorAll(
styleSelector
)
if (linkEls.length) {
linkEls.forEach((el) => {
win.document.head.appendChild(el)
})
}
}, [styleSelector])
return (
<iframe title={title} {...props} ref={contentRef}>
{mountNode && createPortal(children, mountNode)}
</iframe>
)
}

How to fetch new info from database without closing mounted components

I`ve been working in a Svelte SaaS recently and there is an mobile app that updates my db constantly, so then I need to fetch info from db again every 1 minute.
The problem is: Inside some hierarchical components, I have modals that close whenever I update my promise. Is there something that can be done so my user doesn`t need to reopen the modal?
Here is the code that updates my promise ( finishedPromise )
onMount(async () => {
const depots = await depotsPromise;
depots.forEach(depot=> checkedDepots.add(depot._id));
toRouteFilter = toRouteFilter;
let isOnline = setInterval(() => {
DataStorage.get('finished',true).then(finisheds=> finishedPromise = Promise.resolve(finisheds));
}, 60*1000);
return function(){
clearInterval(isOnline);
}
});
Rendering the components:
<div>
{#await filteredRoutes}
Carregando...
{:then routes}
{#if selectedTab == 1}
<ManageDelivery
routes={routes}/>
{:else}
<MapDelivery />
{/if}
{/await}
</div>
My modals are rendered inside the component ManageDelivery, only by using a local inside flag of showModal as true or false.

useState in next.js when navigating using Link (next/link)

I have a next.js page to display a post, like a blog, and I use Link to move from a post to another. To show the proper post I use another component, something like this (note that I cut a lot of code for semplicity)
const Index: NextPage<PageProps> = (props) => {
const router = useRouter();
let post = props.post;
return (
<>
<Post post={post}/>
<Link href={`/post/${encodeURIComponent(props.next.id)}`} passHref={true}>
<a>next post</a>
</Link>
<Link href={`/post/${encodeURIComponent(props.previous.id)}`} passHref={true}>
<a>previous post</a>
</Link>
</>
);
};
export default Index;
export const getServerSideProps = async (context) => {
const session = await getSession(context);
const pid = context.params.pid;
let postManager = new PostManager();
let post = await postManager.getPost(pid);
let siblings = null;
if (post) {
siblings = await postManager.getSiblings(post);
}
return {
props: {
post: JSON.parse(JSON.stringify(post)),
next: (siblings && siblings.next) ? JSON.parse(JSON.stringify(siblings.next)) : null,
previous: (siblings && siblings.previous) ? JSON.parse(JSON.stringify(siblings.previous)) : null,
session: session,
}
};
};
what it is strange is that in the Post component seems like useState is not executed after the first time I load the page:
const Post = props => {
const [title, setTitle] = useState(props.post.title);
console.log(props.post.title);
console.log(title);
here when I load the page "directly" the two values are the same (which is fine). Then when I click on Link (in the page component), the second console.log is showing the value from the content I loaded directly.
This doesn't happen if I take off Link and I leave <a>, but of course using Link is faster so I'd prefer to use it.
How can I "force" useState to set the correct value every time props has changed?
Because you are staying on the same page with shallow routing the component is not freshly re-rendered but the props are updated. This is intended react/next behaviour.
Add to your Post component the following:
useEffect(() => {
setTitle(props.post.title);
}, [props]);
This will update the state when the props are updated.
Let me know if you have any questions.

How to use same page anchor tags to hide/show content in Next.js

The problem
The current project is using Next.js and this situation occurred: the content needs to be hidden or replaced, matching the current category selected. I want to do it without reloading or using another route to do so. And when the user presses F5 or reloads the page the content remains unchanged.
The attempts
Next.js' showcase page apparently is able to do so. In the docs, there's a feature called 'Shallow routing', which basically gives the possibility to update the URL without realoading the page. That's what i figured out for now. Any clues on how the content is changed to match the category?
Thanks!
You can load the content on the client based on the category passed in the URL fragment (# value) using window.location.hash.
Here's a minimal example of how to achieve this.
import React, { useState, useEffect } from 'react'
const data = {
'#news': 'News Data',
'#marketing': 'Marketing Data',
default: "Default Data"
}
const ShowCasePage = () => {
const router = useRouter()
const [categoryData, setCategoryData] = useState()
const changeCategory = (category) => {
// Trigger fragment change to fetch the new data
router.push(`/#${category}`, undefined, { shallow: true });
}
useEffect(() => {
const someData = data[window.location.hash] ?? data.default // Retrieve data based on URL fragment
setCategoryData(someData);
}, [router])
return (
<>
<div>Showcase Page</div>
<button onClick={() => changeCategory('news')}>News</button>
<button onClick={() => changeCategory('marketing')}>Marketing</button>
<div>{categoryData}</div>
</>
)
}
export default ShowCasePage

How can I call a React-Native navigator from an outside MeteorListView file?

This may be more a javascript question than a react-native/meteor question: I am adding Meteor connectivity to an existing React Native app, and have run into a snag with navigation. I previously had a ListView that provided an onPress function each row that would call the navigation. In keeping with Meteor's createContainer protocol, I've used (in my case) a "PuzzlesContainer" in place of the ListView that, in a separate file, refers to
const PuzzlesContainer = ({ puzzlesReady }) => {
return (
<Puzzles
puzzlesReady={puzzlesReady}
/>
);
};
export default createContainer(() => {
const handle = Meteor.subscribe('puzzles-list');
return {
puzzlesReady: handle.ready(),
};
}, PuzzlesContainer);
This file includes the "Puzzles" file, which is also a const function that contains the MeteorListView:
const Puzzles = ({ puzzlesReady }) => {
if (!puzzlesReady) {
return null;//<Loading />;
}else{
return (
<View style={launcherStyle.container}>
<MeteorListView
collection="puzzles"
renderRow={
(puzzle) =>
<View >
<TouchableHighlight style={launcherStyle.launcher} onPress={()=>onSelect(puzzle.text)}>
<Text style={launcherStyle.text}>{puzzle.text}</Text>
</TouchableHighlight>
</View>
. . .
My problem is that there is now no context for the original routing scheme, so when I call
this.props.navigator.push
it gives "undefined is not an object (evaluating 'this.props.navigator')". How can I handle this?
One way is to look at the new NavigationExperimental, which handles nagivator in a redux fashion.
Another method is, even though I do not know if this is recommended or not, to globalize the navigator component by assigning it to a module. It can be something like this
// nav.js
let nav = null
export function setNav = _nav => nav = _nav
export function getNav = () => {
if (nav) {
return nav
} else {
throw "Nav not initialized error"
}
}
Then when you first get hold of your navigator, do this
// component.js
import { Navigator } from 'react-native'
import { setNav } from './nav'
// ...
renderScene={ (route, navigator) => {
setNav(navigator)
// render scene below
// ...
}}
As much as I liked the suggestion of globalizing my navigation, a) I never managed to do it and b) it seemed like maybe not the best practice. For anyone else who might encounter this issue, I finally succeeded by passing the navigation props in each of the JSX tags--so:
<PuzzlesContainer
navigator={this.props.navigator}
id={'puzzle contents'}
/>
in the parent (react component) file, then
<Puzzles
puzzlesReady={puzzlesReady}
navigator={navigator}
id={'puzzle contents'}
/>
in the second 'const' (Meteor container) file, and using it
<TouchableHighlight onPress={()=>navigator.replace({id: 'puzzle launcher', ... })}>
in the third 'const' (MeteorListView) file. Hope it helps someone!

Categories

Resources