I am facing a problem in route how to render the same component in multiple nav link.
I have 2 nav link like this. when I click on edit product, the component render with detail successfully. After that, I click on add a product then component does not render again because component already rendered on the edit product link.
I am using the same component for add and edit.
Anyone can tell me how to Re-render that component on the next click.?
Thanks in advance
<Route
path="/addproduct"
render={() => {
return userData.is_superuser === true ? (
<Product />
) : (
<Redirect to="/dashboard" />
);
}}
/>
<Route path="/editproduct/:id" component={Product} />
Try using render property as follows
<Route path="/editproduct/:id" render={() => <Product/> } />
did you wrap your routes with Switch component?
Just an extra info, you should take a look at react lazy/suspense, is used for code splitting, is useful for decreasing SPAs load times.
I found how to resolve this problem.
You need to use componentWillReceiveProps function in your component.
clicked a link first time by calling url www.example.com/content1/ componentDidMount() is run.
Now when you click another link say www.example.com/content2/ same component is called but this time prop changes and you can access this new prop under componentWillReceiveProps(nextProps) which you can use to call API Or make state blank and get new data.
componentWillReceiveProps(nextProps){
//call your API and update state with new props
}
Related
I am very new to react and just started to build a basic crud application with it. Everything is done besides the update functionality, i got stuck there.I have several bootstrap cards with 2 buttons , delete and update.The data comes from a mysql database and was persisted with hibernate (spring boot on backend).The update button when pressed should pass the id and render a new component(on a different route, guess i need to use Link here) in which a filled form with the respective objects details is presented. Once the user updates the form and clicks submit, he should be redirected to the Cards page. So far i am stuck at the button + Link and rendering the new component phase and for some reason i can't seem to understand how to make it work.This is my code so far
this is my JSX in which i have the Update button which is in the render method of CarList component which has all the cards.
<ReactBootstrap.Card.Body>
<ReactBootstrap.Card.Title>{cars.mark}-{cars.model}</ReactBootstrap.Card.Title>
<ReactBootstrap.Card.Header>Price: {cars.price}</ReactBootstrap.Card.Header>
<br />
<h6>Fabricated: {cars.year}</h6>
<h6>{cars.fuel}</h6>
<ReactBootstrap.Button variant="success" className="cardButtons" id="cardButtonGreen" onClick={() => this.handleClickUpdate(cars.id)}> Update</ReactBootstrap.Button>
<ReactBootstrap.Button variant="danger" className="cardButtons" id="cardButtonRed" onClick={() => this.handleClickDelete(cars.id)}> Delete</ReactBootstrap.Button>
</ReactBootstrap.Card.Body>
</ReactBootstrap.Card>
</div>
}
<br />
</div>
this is my CarList class and the constructor
class CarList extends Component {
constructor(props) {
super(props)
this.state = {
cars: [],
error: "",
deleteError: "",
updateError: "",
updateCarId: null,
buttonWasPressed: false
}
}
here i have the function that is triggered on click.I am sating the state to the id of the object that is in that specific card where the update button is.
handleClickUpdate = (carId) => {
console.log(carId);
this.setState(
{
updateCarId: carId,
buttonWasPressed: true
}
)
}
and lastly i am rendiring the Component MyComp i want to render by passing in the ID.Line is located in component CarList right under where the Card is.
{this.state.buttonWasPressed && <MyComp carId={this.state.updateCarId} />}
What this code gives me so far, is that i am able to set the state as the id, and then use the button to display the component, but it is displayed on the same page, right under the card (where the line of code is also located) instead of displaying it in a new page on a new route.I have tried adding Link,Switch, Route, Router, but i am afraid i am not sure how to use it in this exact context with the button, and it is confusing to me so i was not able to make it work.Can you please help me render "MyComp" on a new page with that id ?
Any help would be greatly appreciated.
what you need is a global store, such as Redux or Mobx. That way you can update the state with relevant data and retrieve them on the new page.
If you need a workaround, you could use history.pushState()
Basically you can push to your location and with it a state.
And on the next page, which is MyComp in this case, you could use history.state to retrieve the pushed data.
I am learning react and I found a video on youtube of someone creating a PWA using a news api, I decided I would try replicate it using react as his video was just in vanilla JS and I learn things a little easier if I build stuff.
on the news API there is a sources and an articles API.
Articles:
https://newsapi.org/v1/articles?source=bbc-news&apiKey=${API_KEY}
Sources:
https://newsapi.org/v1/sources?language=en
I have created a select box which contains the sources from the sources api and I get the news by updating the source in the URL from the select box. I have managed to get the select box to put its value into state onchange but I cant get that up to the NewsItem component to change the source in the articles url.
I have put a codepen together here https://codepen.io/crash1989/pen/JZLQxr it is slightly different to how I have my code, as I have had to create the sources and news manually as I didnt want to publish my API key.
Where you see componentDidMount I am using async/await functions to get the data from the API and putting it into state.
In my actual code I want to have a url like this for the articles https://newsapi.org/v1/articles?source=${this.state.source}&apiKey=${API_KEY}
so the bottom line is I need help getting the select box value into the NewsItem component to update my news.
Your App is build like this
<App>
<Nav />
<News />
</App>
You select a value in <Nav /> and want to pass it to <News />. You should do so by storing the value in the state of App, and pass the value and the changeHandler as property to the children.
class App extends Component {
constructor(props) {
this.state = {
source: "BBC News"
}
}
setSource = source => {
this.setState({source})
}
render() {
let {source} = this.state
return (
<div>
<Nav source={source} setSource={this.setSource} />
<News source={source} />
</div>
)
}
}
I get resources dynamicaly by function. When I change screen-size, I want again run this function. I thought I can add state "screenSize"in admin-component and by resize change state, but when I change state, resources don't render again.
<Admin
customReducers={customReducers}
dashboard={Dashboard}
restClient={restClient}
loginPage={CustomLoginPage}
authClient={authClient}
menu={CustomMenu}
screenSize="medium"
>
//we get thisby auth_get_permissions in authClient
{({ modules}) => loadingResources(modules)}
</Admin>
It's not very efficient to rerender all resources when a screenSize changes, please use the Responsive component. That said, you can create a customLayout and pass it using the appLayout prop of Admin and force an update on that when the screensize prop changes.
I'm building a react/redux app and using a ux library called Grommet in the front end. I have the app set up such that I have a series of forms contained within a set of accordions on the page. Here's a whittled downed version containing only one accordion tab:
handleCpuChange(event) {
console.log(event.target)
this.props.updateStore(
{'general': {'cpus': event.target.value} }
)
}
<Accordion>
<AccordionPanel heading="General">
<Box>
<FormFields>
<FormField label='CPUs'>
<NumberInput
value={this.props.form.formData.general.cpus}
onChange={this.handleCpuChange.bind(this)}/>
</FormField>
<FormField label='Ram'>
<NumberInput
defaultValue={this.props.form.formData.general.ram}
onChange={this.handleCpuChange.bind(this)}/>
</FormField>
</FormFields>
</Box>
</AccordionPanel>
</Accordion>
- All of this works fine. The problem is that when I call the handleCpuChange function is called my state/store value gets updated - but my the actual 'value' or 'defaultValue' fields stay the same. For the most part this is no problem but if I close and reopen the accordion the values in those fields resets to the defaults/values supplied through props. I figured that a nice way around this is to remap the state to props whenever the accordion opens or closes that way the actual value updates - but I'm not sure how to do this without reloading the entire page.
My list component should be able to highlight why a certain element is part of the list based on keywords entered by the user.
I am using the react-highlighter component currently inside the list item, but it requires me to send down the keyword entered by the user from the search box => to the listview => to the list item
That doesn't look very react to me.
I am also using redux so I have only one store, and the listview and items are not directly aware of the store. They are dumb components just rendering properties.
<SearchBox onChange={setSearchText} value={searchText} />
<List items={item} highlight={searchText}>
<ListItem>
<Highlight search={searchText}>{name}</Highlight>
</ListItem>
</List>
Is there a more elegant way to handle such highlighting?
As you mentioned in a comment you could pull up your highlight functionality into a HighlightedListItem component.
<SearchBox onChange={setSearchText} value={searchText} />
<List items={item} >
<HighlightedListItem item={item} highlight={searchText}>
{...stuff}
</ListItem>
</List>
In addition when thinking ahead to maximizing performance, this approach might be easier to reason when adding a shouldcomponentupdate
EX:
// HighlightedListItem
shouldComponentUpdate: function(nextProps, nextState) {
return nextProps.item !== this.props.item ||
nextProps.searchText !== this.props.searchText;
}