I use react-notification-system library, and found my code more or less like this.
import React from 'react';
import Notification from 'react-notification-system';
class Notif extends React.Component {
constructor(props) {
super(props);
this.notificationSystem = null;
}
componentDidMount() {
// how to export this?
this.notificationSystem = this.refs.notificationSystem;
}
render() {
return <Notification ref="notificationSystem" />;
}
}
export default Notif;
How can I export that notificationSystem so I can use it everywhere?
Two ways:
Use global widget.
Just add a global widget as follow.
var _component
export function set(component) {
_component = component
}
export function get() {
return _component
}
And then in your AppComponent register it:
import {set} from './notify'
class App extends React.Component {
componentDidMount() {
set(this.refs.notificationSystem)
}
}
In any other component, call it:
import {get} from './notify'
class AnyComponent extends React.Component {
alert() {
get().doSomething()
}
}
Use react context to store it as a global props for all component.
Related
in the first react file i called an api to get some data and save it in this.state.Data
import React, { Component } from "react";
import axios from "axios";
import Layout from "./Layout";
class Db extends Component {
constructor() {
super();
this.state = {
Data: [],
};
}
componentDidMount() {
axios.get(`https://breakingbadapi.com/api/characters`).then((res) => {
const data = res.data;
this.setState({ Data: data });
});
}
render() {
return <h1>DB working</h1>;
}
}
export default Db;
in the another react file i need to get this.props.Data from Db.js file but i dont know how to get it
import React, { Component } from "react";
import Db from "./Db";
class Filler extends Component {
constructor() {
super();
}
render() {
return <div></div>;
}
}
export default Filler;
for small projects you can use React ContextApi to save states in global level and use it inside components you want.
for big projects you can use state management libraries like Redux. it's too much for small projects.
I've been wondering what would be the better to declare pure functions. And if there is a drawback with declaring them as an util functions. So:
import React, {Component, PropTypes} from 'react';
export const exampleFunction = () => {
};
class ExampleComp extends Component {
constructor(props) {
super(props);
}
render() {
const useExampleFunction = exampleFunction();
return (
<div></div>
);
}
}
ExampleComp.propTypes = {};
export default ExampleComp;
VS.
import React, {Component, PropTypes} from 'react';
class ExampleComp extends Component {
constructor(props) {
super(props);
this.exampleFunction = this.exampleFunction.bind(this);
}
exampleFunction() {
}
render() {
const useExampleFunction = this.exampleFunction();
return (
<div></div>
);
}
}
ExampleComp.propTypes = {};
export default ExampleComp;
Also if we declare this function as a static method of ExampleComp class, would it better practice to export the function as a static class property?
I have a React component that I am trying to test using Enzyme/Jest. I am trying to figure out what the most appropriate test would be to ensure the component has rendered.
My component has a prop shouldRender that, if false, will cause the component to not render. My component looks like this:
import React from 'react';
const propTypes = {
shouldRender: React.PropTypes.bool,
};
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
foo: 'bar',
};
}
render() {
if (!this.props.shouldRender) {
return null;
}
return (
<div>
<span>My component</span>
</div>
);
}
}
MyComponent.propTypes = propTypes;
export default MyComponent;
I have a test that looks like this:
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from '../MyComponent';
describe('MyComponent', () => {
it('Should render if we want it to', () => {
const component = shallow(<MyComponent shouldRender />);
expect(component).toBeDefined(); // Passes
});
it('Should not render if we do not want it to', () => {
const component = shallow(<MyComponent />);
expect(component).not.toBeDefined(); // Does not pass, as component isn't undefined.
});
});
I'd like the second test to fail, as the component isn't rendering. Is there a better way to go about testing whether or not a component has rendered?
Happy to provide any more information if it is needed.
Thanks!
So I've had a chat to some people and decided that maybe I am going about this the wrong way.
It's probably a better idea to determine whether or not this gets rendered by the parent component, otherwise any time I want to use MyComponent, I am going to have to pass this shouldRender prop into it.
MyComponent now looks like this:
import React from 'react';
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
foo: 'bar',
};
}
render() {
return (
<div>
<span>My component</span>
</div>
);
}
}
MyComponent.propTypes = propTypes;
export default MyComponent;
and MyParentComponent that uses MyComponent looks like this:
import React from 'react';
const propTypes = {
myComponent: React.PropTypes.bool,
};
class MyParentComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
boz: 'baz',
};
}
render() {
return (
<div>
{ this.props.myComponent &&
<MyComponent />
}
</div>
);
}
}
export default MyComponent;
Not only does allow MyComponent to be more reusable, it removes the need for the test I wanted to write altogether. Thank you to everyone that looked at this.
I think Jest's snapshot testing is what you need. With snapshot testing when a test fails you can check to see if it's intended or unintended change. Check out their example here
Is it somehow possible to extend component that is being connected by Redux connect() function? For example, if I am inside form-container.js and I'm using
const FormContainer = connect(
mapStateToProps,
mapDispatchToProps
)(Form)
Is there a way to override some methods like this:
FormContainer.componentDidMount = () => ...
Or add custom functions?
You can use High order components for this. I'm borrowing this example from this article
function HigherOrderComponent(WrappedComponent) {
return class NewComponent extends React.Component {
constructor() {
super(props)
this.customMethod = this.customMethod.bind(this)
}
customMethod() {
console.log('You called an injected method');
}
render() {
return <WrappedComponent {...this.props} customMethod={this.customMethod} />
}
}
}
How to use this custom method:
import HigherOrderComponent from './HigherOrderComponent'
class MyComponent extends React.Component {
constructor(props) {
super(props)
}
componentDidMount() {
this.props.customMethod()
}
render() {
...
}
}
const MutatedComponent = HigherOrderComponent(MyComponent)
const ConnectedComponent = connect(
mapStateToProps,
mapDispatchToProps
)(MutatedComponent)
As far as I know, you cannot override life-cycle methods of a React component. But you can inject methods by using HoC.
Here is my super simple enhancer:
'use strict';
import React from 'react';
function BaseComponent(ComposedComponent) {
return class extends React.Component {
static displayName = "BaseComponent";
constructor(props) {
super(props);
}
updateState(obj) {
if (this.isMounted() && obj) {
this.setState(obj);
}
}
render() {
return (
<ComposedComponent {...this.props} {...this.states} />
)
}
}
}
export default BaseComponent;
And I'm enhancing my component as follows:
'use strict';
import React from 'react';
import BaseComponent from '../composits/Base.jsx';
#BaseComponent
class Home extends React.Component {
static displayeName = 'Home';
constructor(props) {
super(props);
}
render() {
console.log(this.updateState)
return (
<div>Hi</div>
)
}
}
export default Home
But this does not work! console.log(this.updateState) is null. What am I doing wrong?
EDIT
Maybe I'm missing something here. By the design I have above, will Home be the "enhanced" component, or BaseComponent? On otherwords, would Home have access to BaseComponent methods/states/props or the other way around?
Give it a name
function baseComponent(ComposedComponent) {
return class BaseComponent extends React.Component {
// ommited
}
}
export default baseComponent;
Or try to wrap it
'use strict';
import React from 'react';
import BaseComponent from '../composits/Base.jsx';
class Home extends React.Component {
// ommited
}
export default BaseComponent(Home);