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?
Related
I am trying to get adaptValue from Component1 and use it in Component2. For some reason this does not work since my adaptValue is always null/undefined. Is it because Parent is a functional component?
const Parent = (props) => {
const [adaptValue, setAdapt] = useState(null);
return (
<div>
<Component1 setAdapt={setAdapt}/>
<Component2 adaptValue={adaptValue}/>
</div>
)
}
export default class Component1 extends Component {
constructor(props) {
super(props);
}
adaptValue = (value) =>{
DO_SOMETHING_WITH_VALUE
}
componentDidMount() {
this.props.setAdapt(this.adaptValue);
}
render() {
return something;
}
}
export default class Component2 extends Component {
constructor(props) {
super(props);
}
someFunction = (value) =>{
...
//adaptValue is always undefined
this.props.adaptValue(value)
...
}
render() {
return something;
}
}
UPDATE Made the parent a class component in the end and all works. Wondering whether this is a compatibility issue between functional or class-based components.
When passing setAdapt to Component1 ... setAdapt is already a function. There is no need to wrap it in another one. Component1 will modify the value, and Component2 will display it. Function Components have nothing to do with the behavior.
Try ...
App.js
import React, { useState } from "react";
import "./styles.css";
import Component1 from "./Component1";
import Component2 from "./Component2";
export default function App() {
const [adaptValue, setAdapt] = useState(null);
return (
<div>
<Component1 setAdapt={setAdapt} />
<Component2 adaptValue={adaptValue} />
</div>
);
}
Component1.js
import React, { Component } from "react";
export default class Component1 extends Component {
handleClick = () => {
this.props.setAdapt("New Value");
};
render() {
return <button onClick={() => this.handleClick()}>Set Value</button>;
}
}
Component2.js
import React, { Component } from "react";
export default class Component2 extends Component {
render() {
return !!this.props.adaptValue ? (
<h1>{`"${this.props.adaptValue}" <- Value of adaptValue`}</h1>
) : (
<h1>adaptValue Not Assigned</h1>
);
}
}
Sandbox Example ...
So I keep div element in my state. I want to change it's className in response to onClick event. I know I could do it with event.target.className but the code below is only the sample of a biggest application and it's not possible to use it there. As a resultant from changeClass function I get
"TypeError: Cannot assign to read only property 'className' of object '#'".
So I wonder is there any other way to do it?
import React, { Component } from "react";
import "./styles/style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
myDiv: [
<div
id="firstDiv"
key={1}
className={"first"}
onClick={this.changeClass}
/>
]
};
}
changeClass = () => {
this.setState(prevState => {
return { myDiv: (prevState.myDiv[0].props.className = "second") };
});
};
render() {
return <div>{this.state.myDiv.map(div => div)}</div>;
}
}
export default App;
Don't put your jsx in state. only add className and state and onChangeClass use this.stateState to update className.
import React, { Component } from "react";
import "./styles/style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
className:"first"
};
}
changeClass = () => {
this.setState({ classNmae: "two" });
};
render() {
return <div>
<div
id="firstDiv"
className={this.state.className}
onClick={this.changeClass}
/>
</div>;
}
}
export default App;
there's a simpler option try this:
import React, { Component } from "react";
import "./styles/style.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
className: "first"
};
}
changeClass = () => {
this.setState({className: "second"});
};
render() {
return <div
id="firstDiv"
className={this.state.className}
onClick={this.changeClass}>
</div>;
}
}
export default App;
You can use Hooks if you use a React version upper than 16.8
import React, { useState } from "react"
import "./styles/style.css"
const App = () => {
const [myClass, setMyClass] = useState("first")
const changeClass = () => {
setMyClass("second")
}
render() {
return <div
id="firstDiv"
className={myClass}
onClick={changeClass}>
</div>;
}
}
export default App
In the js file below we create an integer(ttSelectedItem).
How do you use it on another .js file ?
(Without clicking any button)
Is AsyncStorage solving that problem? If it is true, how?
import React, { Component } from 'react';
import {Platform,StyleSheet,Text,View,Image,ImageBackground} from 'react-native';
import Picker from 'react-native-wheel-picker'
var PickerItem = Picker.Item;
var numberList = [];
var ttSelectedItem,
for (let i = 0; i < 41; i++){
numberList.push(i.toString());
}
export default class yks extends Component<{}> {
constructor(props) {
super(props);
this.state = {
ttSelectedItem : 20,
itemList: numberList,
};
}
onPickerSelect (index, selectedItem) {
this.setState({
[selectedItem] : index,
})
}
render () {
return (
<View>
<Picker style={{width: "100%", height: "100%"}}
selectedValue={this.state.ttSelectedItem}
onValueChange={(index) => this.onPickerSelect(index, 'ttSelectedItem')}>
{this.state.itemList.map((value, i) => (
<PickerItem label={value} value={i} key={"money"+value}/>
))}
</Picker>
</View>
);
}
}
You can create a file ttSelectedItem.js and import it in all the components you need.
Example:
//ttSelectedItem.js
const ttSelectedItem = 'Hello';
export default ttSelectedItem
//YourComponent.js
import ttSelectedItem from './path-to-ttSelectedItem';
class YourComponent extends React.Component {
console.log(ttSelectedItem); // print Hello
}
More info: https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export
You can also pass down the prop from a parent component to its children.
Example:
// App.js
import FirstComponent from 'path-to-first-component';
import SecondComponent from 'path-to-second-component';
class App extends React.Component {
render() {
return (
<View>
<FirstComponent ttSelectedItem={'Hello'} />
<SecondComponent ttSelectedItem={'Hello'} />
</View>
)
}
}
// FirstComponent.js
class FirstComponent extends React.Component {
console.log(this.props.ttSelectedItem) //print Hello
}
export default FirstComponent
// SecondComponent.js
const SecondComponent = (props) => {
console.log(props.ttSelectedItem) //print Hello
}
export default SecondComponent
Depending on how complex your code will be, you can use HOCs to wire up some data and pass down your components
Example:
//ttSelectedItem.js
const ttSelectedItem = (Component) => {
return <Component ttSelectedItem={'Hello'} />
}
export default ttSelectedItem;
//YourComponent.js
import ttSelectedItem from 'path-to-ttSelectedItem';
class YourComponent extends Component{
(...)
console.log(this.props.ttSelectedItem); //print Hello
(...)
}
export default ttSelectedItem(YourComponent);
More detail: https://reactjs.org/docs/higher-order-components.html
Or if you need an even complex code, you can use Redux Store to keep this data
Example using Redux and ReduxThunk:
//App.js
import ReduxThunk from 'redux-thunk';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import reducer from 'path-to-your-reducer';
import YourComponent from 'path-to-your-component';
class App extends Component {
render() {
const store = createStore(reducer, {}, applyMiddleware(ReduxThunk));
return (
<Provider store={store}>
<YourComponent />
</Provider>
);
}
}
// YourComponent.js
import { connect } from 'react-redux';
class YourComponent extends React.Component {
console.log(this.props.ttSelectedItem) // prints Hello
}
const mapStateToProps = function(state){
return {
ttSelectedItem: state.ttSelectedItem,
}
}
export default connect(mapStateToProps, {})(MainAppContainer)
// Reducer.js
const INITIAL_STATE = {
ttSelectedItem: 'Hello',
};
export default (state = INITIAL_STATE) => {
return state;
};
More info: https://redux.js.org/basics/store
The last example is just to show another way to handle data between components using Redux. It should be used only when dealing with really complex data sharing.
I'd suggest you to just follow the first example, it might be enough
Hope it helps
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.
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);