Refresh data from unrelated component React - reactjs

I have a modal that is opened from an AppBar directly which let you insert data in the database.
On the current tab opened in background of modal, you can see a table with the current data, but the modal and the table aren't related. The page with the table is a route /Dashboard while the modal is just the modal, can be opened on front of any route.
I want that after you press the "Add" button in the modal to call the function that makes the get request on the /Dashboard route (which have the same named component).
I know about React Context but I that's all, I don't know exactly how to use it in this case after watching some tutorials.
This is my /Dashboard route:
const DashboardButton = (classes) => (
<Route render={({ history }) => (
<Button
className={classes.button}
onClick={() => { history.push('/Dashboard') }}
>
Dashboard
</Button>
)} />
)
which is in the same AppBar component as the modal.
Thank you for your time.

You might want to add an App level context provider and have a variable there, possibly a boolean or a status that the data should update on Dashboard when you add data from AppBar modal. I made a quick demo, check it out.
https://codesandbox.io/s/blue-dew-8rfho?file=/src/App.js

Related

React Router history on browser's back button

I have a home component with a link which loads a display component and in display component i have the same link which loads the display component again.
if user clicks the link many times in Display Component then there will be a lot of router history.i want that when a user clicks the browser back button it should load the home component not all the previous history.
when i use history.replace("/"); in Display component with onClick event then it works only one time back.but again back is resulting the previous history of Display Component
Routes.js
import Home from "./Components/Home"
import Display from "./Components/Display"
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/:city">
<Display />
</Route>
</Switch>
</Router>
Home.js
<Link to ={`/${city}`} onClick={()=>{dispatch(fetchWeather(city)); }}>Search</Link>
Display.js
<Link to ={`/${city}`} onClick={()=>{dispatch(fetchWeather(city)); }}>Search</Link>
Depending on the version of react router you are using you can just add the replace prop on your Link component in the Display.js file to not push new states on the history stack and instead update the current one.
<Link replace to ={`/${city}`} onClick={()=>{dispatch(fetchWeather(city)); }}>Search</Link>
If you're on an older version where this isn't supported what you can do is have a click handler do this for you
// Display.js file
function Display(props) {
// whatever code you have for this file
const handleViewCity = useCallback((event, city) => {
// prevent the default redirect from happening, were going to manage that ourselves
event.preventDefault()
dispatch(fetchWeather(city))
props.history.replace(`/${city}`)
}, [props.history, fetchWeather])
return (
// your jsx
// keep the href so you get browser builtin functionality like right click "open in new window"
<a href={`/${city}`} onClick={(e) => handleViewCity(e, city)}>Search</Link>
)
}
export default withRouter(Display)
To visualize what would be happening here think of history as a stack of locations. (this is a simple example - pseudo code)
history.push('/city1') // ['/home', '/city1']
history.push('/city2') // ['/home', '/city1', '/city2']
history.push('/city3') // ['/home', '/city1', '/city2', '/city3']
Pressing the browser back button fires a window popstate event. Pop being the keyword there. When the browser back button is pressed your history then looks like this ['/home', '/city1', '/city2'], which is why you were seeing different cities from the history.
Instead you want to use replace to achieve the desired effect
history.replace('/city1') // ['/home', '/city1']
history.replace('/city2') // ['/home', '/city2']
history.replace('/city3') // ['/home', '/city3']

how to show a web page in modal after click

i want to build a registration web page in react, that has a checkbox, and a text along that checkbox. one word in the text is a link to a pdf file which is the terms and conditions for example. now, how can i show that pdf not as a new window tab opened, but instead in the same tab and in a modal. i used the tag with a href attribute but it opened for me a new tab, and i dont know how to get that the modal will open in the page, with like a href link that when the user click on that link (not a button. link) the modal will show.
thanks
If you want to show modal to user, set one state modal, something like this:
const [modalConf, setModalConf] = useState({show:false, mode:''})
and user click the link, you can change the state, like:
setModalConf({show:true, mode:'Terms'})
and finally, you render the modal component like this :
<Modal show={modalConf.show} mode={modalConf.mode} />
and your modal component will get mode component from props:
Modal component:
props.mode === 'Terms' && render Terms
props.mode === 'Privacy' && render Privacy

How to open up a new page when clicked on a button in React.js without using Routers?

I am very new to React (React hooks, etc). My task is to open up a page when clicked on a button. I do not want to change the url in this case. Just open up a new page (just load the new page component on the main page)?
Example,
export function MainPage(){
const [new_page, openNewPage] = useState('');
return (
<header className = "styling_headers">
<button onClick = {() => openNewPage("SetNewPage")} > Click Me </button>
{if (new_page==="SetNewPage")?<NewComponent></NewComponent>: null{""}}
</header>
)
}
Now, after clicking on the button "Click Me", I just want to open a new page completely without changing the URL (ie, keeping the main page url when clicked on the button and moving to the new page), this means that the new page would just be a component of the main page. I do not want to use routers just for opening the new page. I do not want the contents of the main page to reflect on the new page either. It should be a fresh page with only the contents of the new page. How do I achieve this?
-- The new page component --
export function NewComponent (){ // maybe some props will be passed here when clicked on the button.
return (
<div> This is the new page when clicked on the button </div>
)
}
Please can someone modify the above code or direct me in how I can link the NewComponent Page when clicked on the "Click Me" button on the main page without using routers? React hooks or any other React solution is welcome.
I would really appreciate any help. I googled a lot about this, but still haven't found the solution for this. Please help!
Thank you.
If you really don't want to use react-router you can use plain React state and render component accordingly on the current state. Something like this
function MainPage(){
const [page, setPage] = useState("");
return(
<header className = "styling_headers">
<button onClick={() => setPage("MAIN_PAGE")}>
Change to main page
</button>
<button onClick={() => setPage("OTHER_PAGE")}>
Change to other page
</button>
{page === "MAIN_PAGE" ? <MainPage/> : null}
{page === "OTHER_PAGE" ? <OtherPage/> : null}
</header>
)
}
Again you should only use this if you app is small. If your app is big enough doing this may make you app very complicated, consider that you may have other logic in the app

Dynamic Popover in ReactJS

I'm fairly new to React and I'm using the Ant Design framework (https://ant.design/).
I have a table list of items that I'm looking to have a button on each so that when it is pressed additional information about that row becomes available (which is a secondary API call specific to that row).
I'm trying to use a popover but I'm noticing that the popover wants the text before being rendered which is a problem since I don't have that information until the second API call. The best idea I've come up so far is to have the button press trigger the api call and then the state is updated but that creates a funky experience (as it is update after the popover is already opened - after starting with the previous rows information). It isn't a huge amount of time but it still isn't an ideal experience.
This is what I have so far:
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
this.sectionAttributes triggers my fetch request. and this.contentSec does the formatting on the existing popup (see below).
contentSec(props) {
const listItems = this.state.attributes.map((item) =>
<li>{item}</li>
);
return <div><ul>{listItems}</ul></div>
}
Any ideas of a better way to handle this so that there isn't that buggy delay when clicking the button for the popover?
Thanks.
As the content is populated after the second api call, You can send two props content which can be empty string or any default value and loading variable as true on click. Once you have the data after the API call you can send the updated props ie content with actual text and loading as false and finally handle your logic and state update in componentwillrecieveprops() in the popover component.
You can use the loading prop to switch from a loader initially to the actual content.
Write a condition to check if the response from this.sectionAttributes(record['section'] is true, if it is true then
<Popover content={this.contentSec([record['section']])} title=
{record['section']} trigger="click">
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
</Popover>
else simply use
<Button onClick={() => this.sectionAttributes(record['section'])}>
<Icon type="info-circle-o" />
</Button>
For the first time user clicks on button, the component rerenders and state gets updated, so when it rerenders you can see popover as the if condition satisfy.

How to change URLs (but not entire view) when clicking on a modal with Material-ui and react-router 4?

I have an app using a material ui List with ListItems.
I want for users to be able to click on a ListItem and have it open a Modal or a Collapse to give more info about the ListItem. I want the view to stay the same (overall), albeit with a new url that links to that Modal or Collapse.
Right now, all I can get is that the user clicks on the ListItem and it opens an entirely new view.
I want to have the ListDetails or ListItem details be shown in a collapse or modal (or some ui that is on that same page) and be linkable (have a url)
Code:
// List
<List>
<Collapse>
<ListItem <Link to={`/listitem/${listitem.id}`}> />
<ListDetail />
</Collapse>
<ListItem />
<Modal><ListDetail /></Modal>
</List>
// Router
<Route path="/list/:id" render={({ match }) => <ListDetail params={match.params} />} />
This goes to an entirely new page. How to wire it up to so that I can show ListDetail within the same page?
How to set up the components/routing to change urls but just change the UI (and not render an entirely new page?
Do not put <Link to={'/listitem/${listitem.id}'}> there. Instead put an on-click handler with on-click function as this.props.router.push('/bar'). This will cause the route to change.
And when modal is false you can revert the url to previous url using the same method.

Resources