React with REST API - State or GET on mount? - reactjs

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.

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.

Can I make a certain function globally available inside a React application?

It is a common practice to pass in the form of a prop, from a root component A, to a subcomponent B, a function that will change the state of A. Like so:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'foo'
};
this.handleNameChange = this.handleNameChange.bind(this);
}
render() {
return (<NameChanger name={this.state.name} onNameChange={this.handleNameChange} />)
}
handleNameChange: function(newName) {
this.setState({
name: newName
});
}
}
Now as you can see NameChanger is one level down only so not a big issue there. But what if it had been down 3 or even 4 levels? We would have had to pass it down the chain of components and that bothers me big time. Is there a way to make a function globally available within the app?
I looked at Context (https://reactjs.org/docs/context.html) but I am not sure it is the right design choice for globally available functions. Or is it?
Thanks
In a typical React application, data is passed top-down (parent to
child) via props, but this can be cumbersome for certain types of
props (e.g. locale preference, UI theme) that are required by many
components within an application. Context provides a way to share
values like these between components without having to explicitly pass
a prop through every level of the tree.
https://reactjs.org/docs/context.html
Try using Redux or Mobx(very easy to start with) as state management library to solve this problem.

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.

in react Redux how to structure app to decouple component from state atom

in an redux app, using connect to fetch data from state is the way to go. problem is i find my self tighly coupling the component with the state atom.
in case i want to change the structure of the state tree, all components that used to consume such state will break.
so how to decouple them ?
example
initialState = {
users: { ids:[1,2] , byId:{1:{name:'user 1'},2:{name:'user 2'} }
posts: { ids:[1,2] , byId:{1:{title:'post 1'},2:{title:'post 1'} }
access : {1:[1,2],2:[1,2]} //post_id : [user_id who can see post]
}
in this simple state, i'm descriping that i have 2 users, and 2 posts, both posts are visible to both users..
in a component that list posts and users the connect can be
render(){
let {posts,access,currentUser} = this.props;
let my_posts = posts.ids.map(post_id=>posts.byId[post_id])
.filter(post=>(access[post.id].indexOf(currentUser.id)>-1)
//above map will return posts, and filter will filterout posts user dont have access to.
}
connect( (state,prop)=>{currentUser:users[prop.user_id],posts,access})(Component);
<Component user_id={1} />
the problem here is that the render function of the component do lots of manipulation with the state to render correct data. it would be much better if i can do something like
render(){
let my_posts = Posts.ofUser(currentUser.id)
//now Posts should be a service that has access to state and return the needed data.
}
how can i create such Object that deals with the state and expose an api that components and connect functions contact for information.
i read about reselect alot, but how to implement it ?
The easiest way to decouple state shape from your components is querying any of your state prop through selectors.
It adds a bit of boilerplate code, but once is done, you'll get a fully testable bridge between your components and application state.
To get started with selectors, take a look to Redux Docs Computing derivated data page.
Reselect is just an utility to create memoized selectors.

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!

Resources