Manually instantiating ReactNative components? - reactjs

It seems like that in ReactNative that you can do something like new SomeComponent(props) and return someComponent.render(). I'm guessing this is basically what the JSX does when you directly declare <SomeComponent someProp="etc"/>? If that's the case, is there any potential downsides to manually manipulating the components rather than using JSX?

It seems like that in ReactNative that you can do something like new
SomeComponent(props) and return someComponent.render()
Not really. If you manually instantiate a component class, among other things lifecycle methods (componentWillMount(), componentDidMount()) won't work.
I'm guessing this is basically what the JSX does when you directly
declare
Have a look at what babel compiles to, but basically JSX compiles down to plain js:
class Hello extends React.Component {
render() {
return <div>Hello {this.props.toWhat}</div>;
}
}
translates to:
class Hello extends React.Component {
render() {
return React.createElement('div', null, `Hello ${this.props.toWhat}`);
}
}
If that's the case, is there any potential downsides to manually
manipulating the components rather than using JSX
You could use React.createElement and completely avoid JSX, but in my experience this is harder and more verbose. Manually instantiating components though like you initially suggested defeats the purpose of using React :)
Some good links which go in more detail:
https://reactjs.org/docs/react-without-jsx.html
https://reactjs.org/docs/react-component.html

Related

Is there any way to use ComponentDidMount() and ComponentDidUpdate() in Application Customiser Extension in SPFX

I'm trying to implement a webpart code inside a Extension , I was able to do that . But When i run the code ComponentDidMount() ComponentDidUpdate() are not getting called. Is it possible to implement that or it's not possible? I want to know that.
Feel free to share your knowledge
Thanxxx
From a practical point of view, I don't think you want to run a componentDidUpdate() in an extension unless you have a pretty good if statement.
But I think a componentDidMount should work.
In my customizer.ts file, I create the React Element after the Init
const element: React.ReactElement<IAcgBobBotProps> = React.createElement(
AcgBobBot,
{
webChatToken: this.properties.webChatToken
}
);
ReactDom.render(element, this._bottomPlaceholder.domElement);
And I create a component in a new \components\AcgBobBot.tsx TSX file:
export default class AcgBobBot extends React.Component<IAcgBobBotProps, IAcgBobBotState> {
public componentDidMount() {
console.log("Hi from componentDidMount");
}
public render(): React.ReactElement<IAcgBobBotProps> {
...
}
I, personally, also put my React "web part" into a placeholder, exactly copying the code from here: https://learn.microsoft.com/en-us/sharepoint/dev/spfx/extensions/get-started/using-page-placeholder-with-extensions

Abstract component vs. prop passing

I am building an app for posting tutorials. Two of the components I have are EditTutorialForm and NewTutorialForm. These two components are essentially the same except for the methods componentDidMount and onSubmit.
What seems to make the most sense is to have an abstract component type called TutorialForm and to extend it to make EditTutorialForm and NewTutorialForm.
I have read on the React docs that inheritance is not recommended with React. Would it be "better" to pass the componentDidMount and onSubmit functions as props to the TutorialForm component, as opposed to extending the component itself?
I would create one component and check within something like the following:
For a new tutorial
<TutorialForm edit={false}>
To edit a tutorial
<TutorialForm edit={true}>
And in TutorialForm
class TutorialForm extends Component{
componentDiMount() {
this.props.edit ? do edit stuff... : do new stuff
}
submitForm = () {
this.props.edit ? submit edit... : submit new
}
}

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 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!

Using React.createClass instead of ES6 Classes (extends React.Component)?

Is there any harm in using React.createClass to define my components instead of using the ES6 approach where I extend from React.Component?
Below is an example where the Circle component is created using React.createClass and the Circle2 component is created using the ES6 class approach:
var Circle = React.createClass({
render: function() {
return (
<p>Hello</p>
);
}
});
class Circle2 extends React.Component {
render() {
return <p>Hello</p>;
}
}
I have read about the technical differences between both approaches, but am I doing something wrong by telling myself (and others) that using React.createClass is totally OK?
Thanks,
Kirupa
There's no harm in using React.createClass. It's still the official suggestion in the docs and the unofficial suggestion from the devs.
In fact, I'd go as far as to say that I think it's still a better solution than classes, for a few reasons.
Classes don't autobind (without hacks).
Adding static props is not intuitive.
You need third party libraries for mixins.
There are different lifecycle methods.
Object literal syntax is a very intuitive way to define properties and most Javascript developers will be very comfortable with it already.
I've heard it argued that the class syntax is more elegant, but with object literal shorthand and arrow functions, calls to createClass can be pretty expressive too.
const Circle = React.createClass({
render() {
return (
<p>Hello</p>
);
}
});
Of course, more than either of the others you should look for opportunities to use stateless functions instead.
const Circle = (props) => <p>Hello</p>;
They're the simplest option and they resolve a lot of the ambiguity above by simply not including it. It's just a function that takes props as arguments.

Resources