fireOne(){
}
render(){
return(
<p onClick={this.fireOne.bind(this)}></p>
)
}
Can I bind one event with 2 function? one function is for current component, I want to pass something down to the children component as well.
I think this is what you are trying to acomplish, but I'm not completely sure:
class MyComponent extends React.Component {
foo1 = () => { console.log('ahh');}
foo2 = () => { console.log('beh');}
render() {
return(<div onClick={() => {
this.foo1();
this.foo2();
}}>AHH </div>)
}
}
ReactDOM.render(<MyComponent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>
Related
I want to use an React Component as a object to make some calculation based on other components before I render / mount them. I have a working solution but I find the part a.type.prototype.calculate.bind(a)() quite dirty.
Here's my current way (also on JSBin):
class ChildComponent extends React.Component {
calculate() {
return this.props.a + this.props.b;
}
render() {
return <span>{this.props.a + this.props.b} </span>
}
}
class ParentComponent extends React.Component {
render() {
var children = [
<ChildComponent a={2} b={3} key="1" />,
<ChildComponent a={1} b={2} key="2" />
];
var children_sorted = children.slice();
children_sorted.sort((a,b) => {
return a.type.prototype.calculate.bind(a)()
- b.type.prototype.calculate.bind(b)()
});
return (
<h1>Children {children} -> {children_sorted}</h1>
);
}
}
ReactDOM.render(
<ParentComponent/>,
document.getElementById('react_example')
);
<div id="react_example"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
Does somebody have a better way to achieve that?
One way that comes to mind is to make calculate static:
static calculate({a, b}) {
return a + b;
}
...and pass props into it:
children_sorted.sort((a,b) => a.type.calculate(a.props) - b.type.calculate(b.props));
Live Example:
class ChildComponent extends React.Component {
static calculate({a, b}) {
return a + b;
}
render() {
return <span>{this.props.a + this.props.b} </span>
}
}
class ParentComponent extends React.Component {
render() {
var children = [
<ChildComponent a={2} b={3} key="1" />,
<ChildComponent a={1} b={2} key="2" />
];
var children_sorted = children.slice();
children_sorted.sort((a,b) => a.type.calculate(a.props) - b.type.calculate(b.props));
return (
<h1>Children {children} -> {children_sorted}</h1>
);
}
}
ReactDOM.render(
<ParentComponent/>,
document.getElementById('react_example')
);
<div id="react_example"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.2/umd/react-dom.production.min.js"></script>
If the children need to make the same calculation, they can use calculate as well, via ChildComponent.calculate(this.props) (which will always use the version of calculate on ChildComponent or this.constructor.calculate(this.props) which will use the version of calculate on the constructor that created the instance (under normal circumstances). If it's a subclass of ChildComponent and doesn't need its own calculate, it will inherit ChildComponent's (yes, static methods are inherited with class syntax).
Is there a reason for using a component for the calculations?
This can be a simple function. This example could probably be simplified further....
class ParentComponent extends React.Component {
calculate = (a, b) => a + b;
render() {
const children = [this.calculate(2, 3), this.calculate(1, 2)];
const children_sorted = [this.calculate(2, 3), this.calculate(1, 2)].sort();
return (
<h1>
{children.map((x) => x)} => {children_sorted.map((x) => x)}
</h1>
);
}
}
ReactDOM.render(<ParentComponent />, document.getElementById('react_example'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<div id="react_example"></div>
What I'm trying to do is call a function defined in a parent element from its child, but bind this to the child calling the function, rather than the parent where the function runs.
Is there a way to do this and would this be an anti-pattern if so? Thank you.
Parent Function to Pass to Child
onSelect = (event => {
// Some code where `this` is the scope of the child calling the function
// Not the scope of the parent where the function is defined
}
Parent Render Function
render() {
return (
<Child onSelect={this.onSelect} />
)
}
Child Render Function
render() {
return (
<button onClick={this.props.onSelect.bind(this)} />
)
}
The problem is you're defining onSelect as an arrow function, so it closes over this rather than using the this it was called with. Just make it a method or non-arrow function:
class Parent extends React.Component {
onSelect() {
console.log(this.constructor.name);
console.log(this.note);
}
render() {
return <Child onSelect={this.onSelect} />;
}
}
class Child extends React.Component {
constructor(...args) {
super(...args);
this.note = "I'm the child";
}
render() {
return (
<button onClick={this.props.onSelect.bind(this)}>Click Me</button>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
But you might consider binding onSelect once rather than repeatedly (e.g., not in render), perhaps in Child's constructor. But it really only matters if render will get called a lot. E.g.:
class Parent extends React.Component {
onSelect() {
console.log(this.constructor.name);
console.log(this.note);
}
render() {
return <Child onSelect={this.onSelect} />;
}
}
class Child extends React.Component {
constructor(...args) {
super(...args);
this.note = "I'm the child";
this.onSelect = this.props.onSelect.bind(this);
}
render() {
return (
<button onClick={this.onSelect}>Click Me</button>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
Is there a way to do this and would this be an anti-pattern if so?
Pass a function (not an arrow function), and bind it in the constructor.
It's an anti pattern because the parent needs to be aware of the inner working of the child, and this breaks encapsulation.
How do you do that:
Use a standard method, and not an arrow function:
onSelect(e) {
this.setState({
selected: !!e.target.value
});
}
Bind the method in the constructor:
constructor(props) {
super(props);
this.state = {
selected: false
};
this.onSelect = this.props.onSelect.bind(this);
}
Working example:
const { Component } = React;
class Child extends Component {
constructor(props) {
super(props);
this.state = {
selected: false
};
this.onSelect = this.props.onSelect.bind(this);
}
render() {
const {selected} = this.state;
return (
<div>
<input onSelect={this.onSelect} defaultValue="I'm the text" />
<div>{selected ? 'selected' : 'not selected'}</div>
</div>
);
}
}
class Parent extends Component {
onSelect(e) {
this.setState({
selected: !!e.target.value
});
}
render() {
return (
<Child onSelect={this.onSelect} />
)
}
}
ReactDOM.render(
<Parent />,
demo
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="demo"></div>
How can I 'talk' with dom elements with react?
For example - I need to bind some actions with some js lib
Both approaches returns undefined for some reason
componentDidMount() {
const element1 = document.querySelector('.home-container')
const element2 = ReactDOM.findDOMNode(this);
// returns undefined, undefined
console.log(element1.length, element2.length);
}
render() {
return (
<div className="home-container">
...
</div>
)
}
But console.log(element1) returns html from render itself though
How can I work with them?
And what correct lifecycle method for this?
You use "refs":
<div ref={e => {this.div = el}} ...>...</div>
Once your component has rendered, with the above, its div property (you can use any name you want) will refer to the div element that was rendered.
Here's an example largely copied from the link above that focuses a text input when it's rendered:
class AutoFocusTextInput extends React.Component {
componentDidMount() {
this.textInput.focus();
}
render() {
return (
<input type="text"
ref={(input) => { this.textInput = input; }} />
);
}
}
ReactDOM.render(
<AutoFocusTextInput />,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
I am trying to render multiple buttons in react using map but i am getting an errors.
var NameArray = [{"name":"number0"},{"name":"number1"},{"name":"number2"}];
class RenderButtons extends React.Component {
constructor() {
super();
this.onClick = this.handleClick.bind(this);
}
handleClick(event) {
const {id} = event.target;
console.log(id);
}
render() {
return (
<div>
{NameArray.map((obj, index) =>
<h3 id={index} onClick={this.onClick}>
{obj.name}
</h3>
)}
</div>
);
}
}
ReactDOM.render(
<RenderButtons />,
document.querySelector('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
I am using index as Id for my buttons and NameArray properties as name of the buttons.
I tried spliting render of buttons to new function but i am not sure how to do this.
Apparently you miss # sign in your querySelector function.
document.querySelector('#app');
I'm trying to get an instance of the class ActionEditor So that I'd be able to use its methods later:
function render() {
const toRender = responseActions.map((actionInstance) => {
currentActionEditing=actionInstance;
return <li>{ actionInstance === expandedAction ? <ActionEditor id={actionInstance.title} action={getActionByKey(actionInstance.actionType)} instance={actionInstance} state={actionInstance} /> : <button onClick={createOnClick(actionInstance)}>{actionInstance.title}</button>}</li>;
});
ReactDOM.render(
<div>
<div>{toRender}</div>
<button style={styleButtonGenerate} onClick={onGenerateClick}>Generate</button>
</div>,
document.getElementById('root')
);
}
I've attempted to use it through an onClick method like so:
function onGenerateClick() {
var editor = document.getElementById(currentActionEditing.title);
editor.prototype = ActionEditor;
editor.methodIWantToUse();
}
But it always turns out to be null/undefined.
I understand that it's not the best example but it should be enough to demonstrate the issue.
Is there a way around this?
I think what you want here is to save a ref to the component so it can be accessed, see in the example below how the sayHi method is called from the parent component.
class MyComponent extends React.Component {
sayHi() {
console.log('hi');
}
render() {
return (<div>I'm a component!</div>)
}
}
class App extends React.Component {
render() {
// just a way to show how to access a child component method.
setTimeout(() => {
this.node.sayHi();
}, 1000)
return (<MyComponent ref={(node) => this.node = node}/>)
}
}
ReactDOM.render(<App />, document.querySelector("body"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>