React - exporting multiple classes in the same file - javascript

I am working on a project in react where I have multiple components. I am trying to do it all in JSBin (lol.. I know). But i am having issues with exporting multiple classes.
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div></div>
);
}
}
class Bar extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div></div>
);
}
}
export class Foo{};
export class Bar{};
But I am getting an error of
Parsing error: Identifier 'Foo' has already been declared
92 | }
93 |
> 94 | export class Foo{};
| ^
95 | export class Bar{};
So then I tried to change it to this
class Foo extends React.Component {...my code}
class Bar extends React.Component {...my code}
and it compiles but I get an runtime error of
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Is it possible to export multiple classes in a single file with react?

It's because you are re-declaring the class at the bottom, you can export your classes like the following.
export class Foo extends React.Component {
// your code
}
export class Bar extends React.Component {
// your code
}

You can declare your classes as usual, then export all your classes at the end of the file as the following
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div></div>;
}
}
class Bar extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div></div>;
}
}
export { Foo, Bar };
Or if you prefer, you can export the class as you declare them.
export class Foo extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div></div>;
}
}
export class Bar extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return <div></div>;
}
}
Generally its suggested that only export one component per file as per es-lint's rule.

You can also do:
export Foo;
export Bar;
in the end instead of declaring the class again.

Related

React, this.props is not defined

I know this is a very common problem and I looked into many other complaints before posting this.
I have class Parent
class Parent extends React.Component {
constructor() {
super();
this.state = {
...
};
}
....
render() {
return (
<MuiThemeProvider theme={materialTheme}>
<Child
ref={...}
groupId={this.state.groupId}
groupUniqueId={this.state.groupUniqueId} />
</MuiThemeProvider>
);
}
}
And a class Child
class Child extends React.Component {
constructor() {
super(props);
this.state = {
...
};
...
}
getUsers() {
const url = `/someurl/${this.props.groupId}`;
...
}
render() {
return (...);
}
}
export default Child;
However, in the class Child, I get an error
"Uncaught ReferenceError: props is not defined"
Is there something obvious that I am missing? Thanks!
This is happening because your this is not referencing a class. It is referring to your function. You can either use arrow functions or bind this to your function in constructor. Just add below line
constructor() {
super(props);
this.state = {
...
}
this.getUsers = this.getUsers.bind(this)
}

Javascript export a new object instance

export utilities = {
assignOptions: function(newOption, callback) {
//Incorrect 'this' context on second binding
this.props.updateOptions((prevOptions) => Object.assign({}, prevOptions, newOption), callback);
}
};
export const FirstComponent = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);
utilities.assignOptions = utilities.assignOptions.bind(this);
utilities.assignOptions("test"); //'this' context is FirstComponent
}
};
export const SecondComponent = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);
utilities.assignOptions = utilities.assignOptions.bind(this);
utilities.assignOptions("test2"); //'this' context is still FirstComponent instead of SecondComponent
}
};
It seems to be the same instance that's getting exported and so the bindings aren't working.
How do I export a new instance each time?
The issue is likely how JS handles context within objects vs ES6 classes. An easy way to do prop injection like what I think you're attempting is to create an HOC that will wrap your components:
function wrapComponent(ComponentToWrap) {
return class WrappedComponent extends React.Component {
render() {
return <ComponentToWrap {...this.props}/>
}
}
}
This is a simplistic example but think that you can use as much logic as you'd like to inject whatever props you'd like into each WrappedComponent.

React Higher Order Component Initial Props

I am creating a player library and want the React flow to go like this:
PlayerHOC -> PlaylistHOC -> FooterContainer.
The reason I want it to go in this direction is that PlayerHOC has methods on it that PlaylistHOC and FooterContainer need to access (i.e from props).
My code:
class FooterContainer extends React.Component {
render() {
return (
<div>
<div className="jp-type-footer" >
//...
</div>
</div>
);
}
}
class FooterPlayer extends React.Component {
constructor() {
super();
this.options = {
smoothPlayBar: false,
muted: true,
//...
};
}
render() {
return (
<Player {...this.options} />
);
}
};
export const PlaylistHOC = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);
//Add a new stateClass for the extra loop option
this.stateClass = merge({
shuffled: "state-shuffled",
loopedPlaylist: "state-loop-playlist"
}, this.props.stateClass);
}
setPlaylist = () => {}
};
export const PlayerHOC = (WrappedComponent) => class extends React.Component {
constructor(props) {
super(props);
//get passed in props from FooterPlayer and PlaylistHoc
}
play = () => {}
pause = () => {}
};
const Player = PlayerHOC(PlaylistHOC(FooterContainer));
export default connect()(FooterPlayer);
I also pass in props from FooterPlayer to PlayerHOC which works fine. However, I also want to pass in default props from PlaylistHOC to PlayerHOC that will never be updated and I can't figure out how to this while also keeping this flow.
For example: const Player = PlaylistHOC(PlayerHOC(FooterContainer)); this would allow me to pass in initial props from PlaylistHOC and FooterPlayer to PlayerHOC but then I would not be able to access PlayerHOC methods by props.
How do I do this?
I would use const Player = PlaylistHOC(PlayerHOC(FooterContainer)); because a parent component can't receive props from it's children.
Looks like both PlaylistHOC and PlayerHOC are mixins, so they should inherit from the component being wrapped instead of React.Component.
I've changed a code just a little bit to be able to test it, but the key idea of it is how I've extended WrappedComponent instead of React.Component in your mixins.
class FooterContainer extends React.Component {
render() {
return (
<div>
<div className="jp-type-footer">
<button onClick={this.play.bind(this)}>Play</button>
</div>
</div>
);
}
}
class FooterPlayer extends React.Component {
constructor() {
super();
this.options = {
smoothPlayBar: false,
muted: true
//...
};
}
render() {
return (
<Player {...this.options} />
);
}
};
export const PlaylistHOC = (WrappedComponent) => class extends WrappedComponent {
constructor(props) {
super(props);
//Add a new stateClass for the extra loop option
//this.stateClass = merge({
// shuffled: "state-shuffled",
// loopedPlaylist: "state-loop-playlist"
//}, this.props.stateClass);
}
setPlaylist() {
}
};
export const PlayerHOC = (WrappedComponent) => class extends WrappedComponent {
constructor(props) {
super(props);
//get passed in props from FooterPlayer and PlaylistHoc
}
play() {
console.log('playing');
}
pause() {
}
};
const Player = PlaylistHOC(PlayerHOC(FooterContainer));
export default connect()(FooterPlayer);
By the way, try decorators for some really fancy syntax like
#PlayerlistHOC
#PlayerHOC
class FooterContainer {
}
Be warned decorators are not definitive and might change a lot.

React - props is empty when calling a callback function from child

I have a button on my main component, when its clicked its open an "Approval pannel", And when the OK is clicked I am calling a callback function to the main component and doing some logic.
I want to pass the callback function(My reasons), The problem is that when the callback function is called, the props and state are undefined.
Why is that happening? Please tell me if any info is missing.
I have added a partial code here:
class MainComponent extends React.Component {
constructor(props){
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Try these changes
class MainComponent extends React.Component {
constructor(props){
super(props); //1. Call super
this.currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked.bind(this), ...}; // 2.bind this
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
I think you need to make few changes to your React component.
First: In the constructor call super().
Second:: Define currentActionConfig as a state and try using it as this.state.currentActionConfig
Third: Specify the binding on onCommandApprovalOkClicked(). as
onCommandApprovalOkClicked = (commandText) => {} and similary for other functions.
class MainComponent extends React.Component {
constructor(props){
super(props);
this.state = {
currentActionConfig = {onOkClick: this.onGenericApprovalOkClicked, ...}
};
}
onCommandApprovalOkClicked(commandText){
console.log(this.props); <- 'undefined'
}
render(){
return <ActionsApprovalPanel currentActionConfig={this.state.currentActionConfig}/>
}
}
export default class ActionsApprovalPanel extends React.Component {
render()
{
...
return <ChangeIpApproval onOkClick={this.props.currentActionConfig.onOkClick}/>;
...
}
}
Make these changes and see if they work.

How do I call/execute a function from another component in react native?

How do I call other component function in my current component in react native? They are both in different script as well.
Anyone know how to do this in react native?
//ClassOne.js
class ClassOne extends React.Component {
constructor(props) {
super(props);
}
setValue(){
}
}
//ClassTwo.js
class ClassTwo extends React.Component {
constructor(props) {
super(props);
}
callSetValue(){
ClassOne.setValue(); HOW???
}
}
You can pass in ClassOne.setValue as a property to ClassTwo.
//ClassOne.js
class ClassOne extends React.Component {
constructor(props) {
super(props);
}
setValue(){
// Do stuff
}
}
//ClassTwo.js
class ClassTwo extends React.Component {
constructor(props) {
super(props);
}
callSetValue(){
if (this.props.onSetValue) this.props.onSetValue(); // this can be set to any function, including ClassOne's setValue
}
}
Unless the function you are wanting to call is static you must instantiate whatever class you want inside the scope of where you want to call the function. Say in ClassTwo you want to call a method in ClassOne... Instantiate an instance of ClassOne inside of ClassTwo and then call the function using that object.
Obviously, it is not a recommended way in ReactJS, even React-Native. Maybe you wanna follow the object-oriented programming rules but here we have fully functional development in ReactJS. for such your case I prefer to use a helper function and in both of the classes, I import and use the helper function:
// set value helper function
export const setValueHelper = () => {
// do something
};
Then in the classes:
import { setValueHelper } from 'helpers';
//ClassOne.js
class ClassOne extends React.Component {
constructor(props) {
super(props);
}
setValue(){
setValueHelper();
}
}
import { setValueHelper } from 'helpers';
//ClassTwo.js
class ClassTwo extends React.Component {
constructor(props) {
super(props);
}
setValue(){
setValueHelper();
}
}

Categories

Resources