ReactJS - Triggering Re-render from external Process - reactjs

Im very new at React and Frontend development. Its literally my first Project now and I have design problem listening to external events. So basically I want to build a UI that only changes on external Events, meaning you control it with another Process (e.g. an AI that triggers the changes). The App should listen to incoming messages and depending on the message it should update the UI.
My idea was to make the Component, that receives the messages from outside, an observable and notify the MainApp of the React-Ui. The following code should give an idea to my approach.
export default class App extends Component {
constructor(props){
super (props);
this.state = {mode: "idle"};
this.observable = new Observable();
this.observable.add((m) => mode(m));
}
mode(m){
this.setState({
mode: m
});
}
render() {
return (
<div>
<Home/>
<ComponentA mode={this.state.mode}/>
<ComponentB mode={this.state.mode}/>
</div>
)
}}
My Question now is, Is this a good way to update the UI or are there maybe better ways or pattern that I can use or that are common in Frontend-Development?

Your approach is totally valid, I don't see any issues with it.
You could try initializing the observable in a lifecycle method instead like componentDidMount. You could even use redux to manage the data passed from the observable.

Related

How prevent calling same api in different components in react js

I am working large reactjs application,In that application so many components are there and so many api services also there.
My problem is how to prevent calling same api in different components.
Actually i want to call api one time then ,i will use that api response entire application ,so that we can prevent calling same api in different components.
So please give me any solution.
check the below demo code:
enter code here
`FirstComponent:
——————————————
Class FirstComponent extends Component {
constructor(props){
this.setState={}
}
componentDidMount() {
this.props.dispatch(getById(1)); //here first time I am calling api
}
render(){
return(
———HTML Code HERE———
)
}
const mapStateToProps = state => {
  return {
    registrationData: state.RegistrationDemand.registrationData
// here I am getting response through redux reducer store
    };
};
export default compose(
  translate,
  withRouter,
  connect(mapStateToProps)
)(FirstComponent);
SecondComponent:
——————————————
Class SecondComponent extends Component {
constructor(props){
this.setState={}
}
componentDidMount() {
this.props.dispatch(getById(1)); //here I need to prevent this second time api calling
}
render(){
return(
———HTML Code HERE———
)
}
const mapStateToProps = state => {
  return {
    registrationData: state.RegistrationDemand.registrationData
//without calling second component,If I use this one first time when I redirect to this page data is coming hereabout when I refresh second time it is getting null.
    };
};
export default compose(
  translate,
  withRouter,
  connect(mapStateToProps)
)(SecondComponent);`
You can actually call the API once your application is mounted. Usually this is done via componentDidMount or if you're using hooks, you can add it inside useEffect.
And you can just pass down props.
A more better solution is to use redux to your project, wherein the whole state of your application is inside a store in which you can connect using react-redux.

How to globally disable/hide/replace a component by name in React?

I have a large React app and I have a few components that I would like to completely disable from a config or global level. Is there any kind of global hook that I can use that is called before any component is rendered? If so, I imagine I can check the name of the component and return null if the name is on the disabled list. How would you do this?
There are a lot of ways to do this:
React's Context API allows you pass props through every level of the component tree so you can use them as flags to enable/disable components. Should be used sparingly however.
Higher Order Components are basically just functions that return a component. You could wrap your components in logic to render them as needed.
Or of course you could use a global state manager like redux to set global states.
There are many ways to do this, so, I'll just describe one simple way: using references and updating the states accordingly.
Full working feature hide/showing sandbox online: codesandbox.io ReactJS Feature Hide/Show Demo
Defined are two classes, class Feature extends React.Component and class App extends React.Component. The render() for <Feature/> is...
render() {
if (!this.state.enabled) {
return <div />;
}
return (
<div className="Feature">
<h1>My Feature!</h1>
</div>
);
}
And the option for enabling/disabling a feature in <App /> would handle display/hiding like so...
handleOnClick(e) {
if (e.target.checked) {
this.feature.setState({ enabled: true });
} else {
this.feature.setState({ enabled: false });
}
}
Of course, you need to make sure that <Feature /> has the reference set...
<Feature
ref={instance => {
this.feature = instance;
}}
/>
If you need simplest solution just use browser global vars and check it in render.
render() {
if( window.globalFlag ) return null
return (
<div> feature content...
Drawbacks:
modifying component,
using global scope,
some unnecessary code can be run earlier (f.e. constructor) and later (f.e. componentDidMount).
Use HOCs - wrap your component - connecting with global store using redux or context API.
<FlagsProvider store={flagStore}>
<SomeComponent_1>
<SomeComponent_2>
<FlagsConsumer flag="someFeatureFlag">
<SomeFeatureComponent />
<FlagsConsumer/> connects to store (redux connect would be an inner wrapper - composing HOCs) and conditionally renders <SomeFeatureComponent /> (or null).
Of course HOC can pass received props to wrapped component - it can be functionally transparent.
Don't reinvent the wheel - use some ready module, read tutorials, google for sth suitable.
HOC can also play a role of A/B testing.

Firebase and React with react-snapshot (pre-rendering)

I"m new to firebase, just wrote a little simple test react component before putting all of data on to firebase, but unfortunately I couldn't make it work with Server Side Pre-Rendering. It's very important to make it SEO friendly for me, and I've searching around on the internet for the solution, but still couldn't really figure it out. please help me out with this. thanks very much in advance.
The simple code below will only generate the initial state with React-Snapshot, when I open the the page it will show initial state and then update to newer state. But I need to make the initial state object fetching data directly from Firebase and generate static html with React-Snapshot.
class FirebaseTestingComponent extends Component {
constructor(){
super();
this.state = {
speed: 10
};
}
componentWillMount(){
const rootRef = firebase.database().ref().child('react');
const speedRef = rootRef.child('speed');
speedRef.on('value', snap => {
this.setState({
speed: snap.val()
});
});
}
render(){
return (
<div>
<h1>{this.state.speed}</h1>
</div>
);
}
}
By SEO friendly I assume you want static content instead of dynamic (not an expert on SEO) but firebase runs asynchronously especially when you use .on() that's like websocket, doesn't matter if you do willmount or didmount this case.
My humble suggestion for the design is to fetch from firebase in your server before render the page (firebase support java and node for sure, not sure about the rest), and set initial state with that value you fetched, that will guarantee your initial state is from firebase. From that you can still use that .on() for later value coming in.

In componentDidUpdate refs is undefined

I want to use Chart.js on my website. As you can see title, I'm using React.js. To use Chart.js, I need the canvas and context like this:
let context = document.getElementById('canvas').getContext('2d');
let chart = new Chart(context, ...);
so I design the component like this:
export function updateChart() {
let context = this.refs.chart.getContext('2d');
let chart = new Chart(context ,... );
...
}
export default class GraphChart extends React.Component {
constructor() {
super();
updateChart = updateChart.bind(this);
}
componentDidMount() {
updateChart();
}
render() {
return <canvas ref="chart" className="chart"></canvas>;
}
}
as you can see, I exported two things, update chart function and GraphChart class. Both will using in parent component like this:
import { updateChart } from './GraphChart';
import GraphChart from './GraphChart';
class Graph extends React.Component {
...
someKindOfAction() {
// update chart from here!
updateChart();
}
render() {
return (
<div>
<SomeOtherComponents />
<GraphChart />
</div>
);
}
}
then Parent class using exported updateChart function to update chart directly. It was working, but only first time. After unmount and mount the GraphChart component, it's refs are just empty.
Why refs is empty? And If I did wrong way, how can I get canvas context for initialize Chart.js?
Object refs is undefined, because this is not what you think it is. Try logging it.
The function you’re exporting is not bound to this of your component. Or perhaps it is, but to the last created instance of your component. You can never be sure that’s the mounted instance. And even if you are, you can not use multiple instances at the same time. So, I would dismiss this approach entirely.
Other than that, providing the function to alter some component’s state is exactly the opposite of what’s React is trying to accomplish. The very basic idea is that the component should know to render itself given some properties.
The problem you are trying to solve lies in the nature of Canvas API, which is procedural. Your goal is to bridge the gap between declarative (React) and procedural (Canvas) code.
There are some libraries which do exactly that. Have you tried react-chartjs? https://github.com/reactjs/react-chartjs
Anyways, if you’re wondering how the hell should you implement it the “React way”, the key is to declare properties your component handles (not necessarily, but preferably), and then to use component lifecycle methods (e.g. componentWillReceiveProps and others) to detect when properties change and act accordingly (perform changes to the canvas).
Hope this helps! Good luck!

React with REST API - State or GET on mount?

We're currently building a React-Redux frontend with a REST API backend powered by Node. I'm unsure about whether to use a Redux or a simple call to the API on mounting the component.
The component is a simple list of profiles which are going to be displayed throughout (but not constantly) the site.
Sorry for asking this. Maybe there's something to read through available?
I would advice you to take a look at two things:
1) The first React tutorial on Facebook is very underrated:
https://facebook.github.io/react/docs/thinking-in-react.html
It exposes a very clear way to think about how to think about the tree structure of your views.
2) From there, move to reading about Containers and Components:
https://medium.com/#dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
This post explains that React components too often do two things: act as renderers and as controllers (taking on both the V and the C on MVC).
Now, what your React view needs is a controller. Fetching it whenever you mount the component overlaps two different concerns: how to display the information and how to fetch it.
You could do it with a single, bigger React component that manages the complete state of your application:
class MyApp extends React.Component {
componentDidMount() {
fetch('/profiles').then(res => res.json().then(::this.setState))
}
render() {
if (this.state) {
return <ProfileList profiles={this.state} />
} else {
return <span>Loading...</span>
}
}
}
That would be your "Container". Your "Component" is a pure representation of the list of profiles, that needs not care about how that information was retrieved:
class ProfileList extends React.Component {
render() {
return <ul>
{
this.props.profiles.map(
profile => <li key={profile.id}>{profile.name}</li>
)
}
</ul>
}
}
Redux is just another way of doing this that enables better reuse of information, and makes that same information available to different components (hiding the instance of the "store" as a mixin). That MyApp class on top of your structure serves a similar function to the Provider class in redux: allowing child components to access information needed to display themselves.

Resources