PubSub not working within route components - reactjs

I was trying to pass data within route components. Since the react-router-dom remove props for class components in the latest version (v6), I just imported pubsub.js and tried to pass the data through the Link with an onclick event.
Here is the component waiting for publishing (showing part of codes).
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import PubSub from 'pubsub-js';
export default class ProductDetails extends Component {
state = {
product: {}
}
componentDidMount() {
PubSub.subscribe('product', (_, product) => {
this.setState({product})
})
}
render(){...}
}
Here is the component passing the data:
import React, { Component } from 'react'
import { Link } from 'react-router-dom';
import PubSub from 'pubsub-js';
export default class ProductHome extends Component {
pubProduct = (product) => {
return () => {
PubSub.publish('product', product)
}
}
...
render(){
const product = {a: 1}
<Link
to='/product/details'
onClick={this.pubProduct(product)}
> Details </Link>
...
}
Both of them are route components. I also tried publishSync but still not working. After click the Link, the state in the ProductDetails component did not change.
If router doesn't support pubsub, how to pass data then? I know using hook apis in react-router-dom v6 could be the best way to handle this kind of problem. But for class components, is there a good way to pass any data within route components in v6?
Thanks!

Related

How to include the Match object into a Reacts component class?

I am using react router v5, and trying to get URL parameters by props match object into my react component class. However it is not working! What am I doing wrong here?
When I create my component as a JavaScript function it all works fine, but when I try to create my component as a JavaScript class it doesn't work.
Perhaps I am doing something wrong? How do I pass the Match object in to my class component and then use that to set my component's state?
here code:
import React, { Component } from 'react';
import { Link} from "react-router-dom";
export class JobDetail extends Component {
state = {
// jobsData: [],
}
async componentDidMount() {
const props = this.props.match;
console.log("---props data---",props); // it's showing undefined
}
render() {
return (
<>
test message
</>
)
}
}
export default JobDetail

React Hook error when loading Solid webId profile

I'm trying to use Solid's react-components to load a user's profile from their webId. I'm running into a problem with useLDflex(). There problem seems to be something to do with React Hooks, but I can't figure it out. My goal is to load the user's profile when the page loads; open to making whatever changes necessary. I'm using MobX for state.
Below is the code and below below is the error in the compiler/web browser. Thank you.
Code (React/JSX/TypeScript):
import React from 'react'; // 16.14.0
import { observer } from 'mobx-react';
import { observable } from 'mobx';
import { useLDflex } from '#solid/react'; // 1.10.0
#observer
export class Profile extends React.Component<{profileId: string}, {}> {
#observable webId = `https://${this.props.profileId}.solidcommunity.net/profile/card#me`;
#observable name = useLDflex(`[${this.webId}`)[0];
render() {
return (
<main role="Profile">
<div className="container">
webId: https://{this.props.profileId}.solidcommunity.net/profile/card#me
Name: {this.name}
</div>
</main>
)
}
}
Error:
src/components/profile/index.tsx
Line 9:24: React Hook "useLDflex" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
You cannot use React Hooks inside class component, ref here: https://reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both
So you need to rewrite it to functional component with Mobx, or make a higher order component and pass the props into your class component (when your class is too complex to rewrite)
With FC:
import {observer} from "mobx-react";
const Profile = observer(({ profileId }) => {
// ...
const name = useLDflex(`...`);
// ...
})
HOC
const withName = (Component) => ({ profileId }) => {
const name = useLDflex('...');
return <Component name={name} profileId={profileId} />
}
export default withName(Profile);

What is the best way to change the URL onClick or onSubmit in a React Class Component?

I'm aware of the useHistory hook for functional components in React, but in my application I have a class component that I want to make able to change the URL.
Is there an equivalent of useHistory for class based components? If not, what is the accepted way to accomplish this?
May be you need something like this:
import { withRouter } from 'react-router-dom'
export const Component = withRouter(({ history, location }) =>{
})
class Comp extends Component {
render(){
const { location, history } = this.props
}
}
export default withRouter(Comp)
A similar question answered here : https://stackoverflow.com/a/58122270/7306148

React router 4 nested routes not working

I am trying to create a nested route - When user logs in it opens dashboard and when dashboard open i want to create a nested route by making a side menu and change the content at the right but not able to do. When I am trying to access the post page in dashboard it is not opening.
import React from 'react';
import { Switch, Route, Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { userActions } from '../_actions';
import { PostPage } from './PostPage';
import { HomePage } from '../HomePage';
class DashboardPage extends React.Component {
render() {
const { url } = this.props;
return (
<div>
<h1>BasicRouting</h1>
<p>With the help of "Match" Component we can specify the Component we want to render for a particular pattern of the App location/window.pathname.</p>
<p>Select a level from Left Navigation to view the content, also notice the change in URL.</p>
<div className="rightContent">
<p>Second Level Content will appear here:</p>
<Route path={`${this.props.match.url}/post`} component={PostPage} />
</div>
</div>
);
}
}
function mapStateToProps(state) {
console.log(state)
return {
isLoggedIn: state
};
}
const connectedDashboardPage = connect(mapStateToProps)(DashboardPage);
export { connectedDashboardPage as DashboardPage };
There are several problems in your code.
You import { Switch ... } from 'react-router-dom', but never used it afterward.
If you want to call the route in upper/parent components, you need to import { withRouter } to wrap the redux connected class, something like,
const connectedDashboardPage = connect(mapStateToProps)(DashboardPage);
const withRouterConnectedDashboardPage =
withRouter(connectedDashboardPage);
export default withRouterConnectedDashboardPage;
Final suggestion, read through the tutorial here:
https://medium.com/#pshrmn/a-simple-react-router-v4-tutorial-7f23ff27adf
&
always refer to: https://reacttraining.com/react-router/

React Router, access history object from child components

I'd like to listen to location change using history.listen in one of deep nested child component.
Should the top parent component which has this.props.history pass down the props all the way down to the child components?
I'm using 2.8.1 react-router
I am willing to upgrade to newer version if it allows me to do this easily.
import { withRouter } from 'react-router-dom';
class MyComponent extends React.Component {
render() {
// props also has match, location
const { history } = this.props;
...
}
}
export default withRouter(MyComponent);
You could get history by getting router context.
import React, {PropTypes} from 'react';
class myComponent extends React.Component {
render() {
console.log(this.context.history);
}
}
myComponent.contextTypes = {
history: PropTypes.object
}
export default myComponent;

Resources