declaring jsx element as a global variable - reactjs

Hello is there a way to declare react component globally so that when I render the same component the values are persisted, I am aware the redux or some other state management lib can be used, but for the time being I want to use this option cuz I'm in the middle of the project. For example
constructor() {
this.accountInfoJSX = <AccountInformation ref={(sender) => {
this.accountInformationMod = sender;
}} />;
}
I can try to save the element in the global variable but each time when the render is called it initializes a new instance.
Edit:
yes sure. i have this method. I have 2 buttons on screen based on which i render different components. User can made some changes on each component, so i am trying to to use same component so that the changes made in component are persisted. i have tried returning this.accountInfoJSX as well as this.accountInformationMod not its not working. On former it re render the new component and values are lost and on latter it show nothing on screen.
get getCurrentScreen() {
if (this.state.selectedScreen == Screens.accountInformation) {
return this.accountInformationMod;
} else if (this.state.selectedScreen == Screens.myInformation) {
return <MyInformation />;
}
}

Related

React can not access variable from return

I am very new to React and I can not solve this issue for a very long time. The idea is the following, I get some user info from database and pass it into cookies. From react side I get this cookies as JSON object and I need to render menu for user depending on values in this object. Right now I pass this object that I get from cookies from parent Component and I try to access it from Settings component. The issue is that I can see access this object from test function, however when I try to access this data from return it gives me undefined error. The function that returns value from cookies is sync, I have no idea why that might happen, please help.....
Since this.state.shopSettings["new_orders"] is boolean, use ternary.
Don't copy props to the state inside constructor as the constructor is executed only once. So updates to the props won't be reflected in the component.
Like this
<button onClick={this.test}>
{props.shopSettings && (props.shopSettings["new_orders"] ? 'true button' : 'false button')}
</button>
It solves very easily with this code, now I can access any key from shopSettings inside return without any issues
class Index extends React.Component {
state = {
shopSettings: Cookies.getJSON('shopSettings')
}
render() {
const {shopSettings} = this.state
if (!shopSettings) {
return null
}
return (
<div>Hello</div>
)
}

Preserve internal state on page refresh in React.js

It must be pretty regular issue.
I'm passing props down to the children and I'm using it there to request to the endpoint. More detailed: I'm clicking on the list item, I'm checking which item was clicked, I'm passing it to the child component and there basing on prop I passed I'd like to request certain data. All works fine and I'm getting what I need, but only for the first time, ie. when refreshing page incoming props are gone and I cannot construct proper URL where as a query I'd like to use the prop value. Is there a way to preserve the prop so when the page will be refresh it will preserve last prop.
Thank you!
(You might want to take a look at: https://github.com/rt2zz/redux-persist, it is one of my favorites)
Just like a normal web application if the user reloads the page you're going to have your code reloaded. The solution is you need to store the critical data somewhere other than the React state if you want it to survive.
Here's a "template" in pseudo code. I just used a "LocalStorage" class that doesn't exist. You could pick whatever method you wanted.
class Persist extends React.Component {
constuctor(props) {
this.state = {
criticalData = null
}
}
componentDidMount() {
//pseudo code
let criticalData = LocalStorage.get('criticalData')
this.setState({
criticalData: criticalData
})
}
_handleCriticalUpdate(update) {
const merge = {
...LocalStorage.get('criticalData')
...update
}
LocalStorage.put('criticalData', merge)
this.setState({
criticalData: merge
})
}
render() {
<div>
...
<button
onClick={e => {
let update = ...my business logic
this._handleCriticalUpdate(update) //instead of set state
}}
>
....
</div>
}
}
By offloading your critical data to a cookie or the local storage you are injecting persistence into the lifecycle of the component. This means when a user refreshes the page you keep your state.
I hope that helps!

Why is using refs slowing down my React application?

I need a few refs of elements to be stored in Redux so that the elements can be focused on.
I have this dropdown:
<BasicSelect
selectRef={(e) => this.storeRef('make', e) } ... />
And here is storeRef:
storeRef(list, ref)
{
if(this.state.refsStored[list]) {
return;
} else {
this.props.storeSelectRef(list, ref);
var refState = Object.assign({}, this.state.refsStored);
refState[list] = true;
this.setState({refsStored: refState});
}
}
From this, it should store the ref once, then simply return after comparing.
However, every time a option in the dropdown of <BasicSelect> is clicked on, the application hangs for a <1s (noticable), and then continues on.
If I change storeRef to the following (obviously the intended result doesn't work):
storeRef(list, ref) {
return;
}
The dropdown selection is super fast, and all is good. So how come this comparison if(this.state.refsStored[list]) is significantly slow?
Don't put refs into component state. Component state should only be used for things that you will need when rendering, and should cause a re-render when you update them. Save refs directly onto the component instance:
<BasicSelect selectRef={selectInstance => this.selectInstance = selectInstance} />
I'm also kind of confused what selectRef is as a prop, to be honest, but I assume that the <BasicSelect> component forwards that ref on to an underlying <select>tag?
Anyway, the key point is that you are causing unnecessary re-renders every time because you're calling setState(). Don't do that.

Best practice for dynamic routing (react router v4) needed?

With React Router V4 being out only for a little while and there being no clear documentation on dynamic routing [akin to transtionsTo(...) in V3] I feel like a simple answer to this question could benefit many. So here we go.
Lets assume the following theoretical scenario: one has a component Container, which includes two other components (Selection and Display). Now in terms of functionality:
Container holds a state, which can be changed by Selection, Display shows data based on said state.
Now how would one go about changing the URL as well as the state triggered by a change in state via react router?
For a more concrete example please see (React Router V4 - Page does not rerender on changed Route). However, I felt the need to generalize and shorten the question to get anywhere.
Courtesy to [Tharaka Wijebandara] the solution to this problem is:
Have the Container component provide the Selection component with a callback function that has to do at least the following on Container:
props.history.push(Selection coming from Selection);
Please find below an example of the Container (called Geoselector) component, passing the setLocation callback down to the Selection (called Geosuggest) component.
class Geoselector extends Component {
constructor (props) {
super(props);
this.setLocation = this.setLocation.bind(this);
//Sets location in case of a reload instead of entering via landing
if (!Session.get('selectedLocation')) {
let myRe = new RegExp('/location/(.*)');
let locationFromPath = myRe.exec(this.props.location.pathname)[1];
Session.set('selectedLocation',locationFromPath);
}
}
setLocation(value) {
const newLocation = value.label;
if (Session.get('selectedLocation') != newLocation) {
Session.set('selectedLocation',newLocation);
Session.set('locationLngLat',value.location);
this.props.history.push(`/location/${newLocation}`)
};
}
render () {
return (
<Geosuggest
onSuggestSelect={this.setLocation}
types={['(cities)']}
placeholder="Please select a location ..."
/>
)
}
}

React Router "Link to" does not load new data when called from inside the same component

Background
I am building an app with the following details
react
react-router
redux
it is universal javascript
node js
Problem
When routing with the Link tag from component to component it works perfectly. It calls the data that the component requires and renders the page. But when I click on a Link that uses the same component as the current one all I see is the url change.
Attempts
Things I have tried to get this to work.
Attempt 1
So far I have tried the steps in this question but the solution wont work for me. This was the code I implemented
componentWillReceiveProps(nextProps) {
if (nextProps.article.get('id') !== this.props.article.get('id')) {
console.log('i got trigggerd YESSSSSSSSSSSSSSS');
}
}
But the variable nextProps is always the same as the current props.
Attempt 2
I decided to call the same code I use in componentWillMount but that didn't work either.
componentWillMount() {
let { category, slug } = this.props.params;
this.props.loadArticleState({ category, slug });
}
It just creates an infinite loop when I put this into componentWillReceiveProps.
Conclusion
I belief the problem is clicking the link never calls the data associated with it. Since the data is loaded with
static fetchData({ store, params }) {
let { category, slug } = params;
return store.dispatch(loadArticleState({ category, slug }));
}
Any help is appreciated.
Solution I Used
I created a function to test if the previous data is the same as the changed data.
compareParams(prevProps, props) {
if (!prevProps || typeof prevProps.params !== typeof props.params) {
return false;
}
return Object.is(props.params, prevProps.params);
}
So this tests
are there any previous props?
and then if the props are equal to the previous props?
then return false if there are if this is the case
if not then we see compare props and previous props parameters
In ComponentDidUpdate
In the compoonentDidUpdate we use this function to determine if the data should be updated
componentDidUpdate(prevProps) {
if (this.compareParams(prevProps, this.props)) {
return;
}
this.props[this.constructor.reducerName](this.props.params);
}
Conclusion
This code updates the body of a page that uses the same react component if it receives new data.
maybe you can try use onChange event on Route component, check Route API and then signal to child component that refresh is needed...

Resources