My first component is as follow:
const hellos = ['Hola', 'Salut', 'Hallo', 'Ciao', 'Ahoj', 'Annyeong-haseyo', 'Aloha', 'Howdy', 'Ni Hao', 'Konnichiwa']
export class Welcome extends Component {
constructor(props) {
super(props);
this.state = {
errors: []
};
}
sayHello = function() {
return hellos[Math.floor((Math.random()*hellos.length))];
}
render() {
return (
<div className="Welcome">
</div>
);
}
}
I want to be able to call sayHello() from another component. All answers I've seen so far talk about parent and child relationships but in this case the two components don't have any relationship. I thought of something like this but it doesn't do the job:
import { Welcome } from './Welcome'
export const Life = () => (
<div className="Life">
<p>{ Welcome.sayHello() }</p>
</div>
)
I would like to get a random element of the hellos array printed in Life.
There are a number of ways you could achieve this:
You can do this by creating the sayHello function and using it simply as a named-function.
hello.js
const hellos = ['Hola', 'Salut', 'Hallo', 'Ciao', 'Ahoj', 'Annyeong-haseyo', 'Aloha', 'Howdy', 'Ni Hao', 'Konnichiwa'];
const sayHello = function() {
return hellos[Math.floor((Math.random()*hellos.length))];
};
export { sayHello };
Then you can import into which ever component you wish to share the functionality:
import { sayHello } from './hello';
class CompA extends React.Component {
render() {
return <span>{sayHello()}</span>;
}
}
class CompB extends React.Component {
render() {
return <span>{sayHello()}</span>;
}
}
render(<span>
<CompA />
<CompB />
</span>, document.querySelector('#app'));
Created a https://www.webpackbin.com/bins/-KkgrwrMGePG4ixI0EKd
Another way, is to simply define your sayHello Function as static.
static sayHello() {
return hellos[Math.floor((Math.random()*hellos.length))];
}
Related
In React can methods be passed to {this.children} in a container consumer model. What I mean to ask is I have a provider component and I need to pass or refer the provider components methods in the child component.
export default class ContainerCompo extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
return (
{this.props.children}
}
}
export default class InputComponent extends React.Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
validate() {
ContainerCompo.methodOne(param)
}
render() {
return <InputComponent />
}
// Rendering the components
<ContainerCompo>
<InputComponent containerMethods={methods of ContainerCompo}/>
</ContainerCompo>
I hope my question is clear here, please suggest
First create a react context.
import React, { Component, createContext } from 'react';
// Create's authentication context to be use anywhere in the app
const ContainerContext = createContext();
export default ContainerContext;
Then create a provider for it.
export default class ContainerProvider extends Component {
constructor(props) {
super(props);
this.myHocComponent = null;
}
methodOne() {
//some code
}
methodTwo() {
//some code
}
render() {
const { children } = this.props;
return (
<ContainerContext.Provider
value={{
container: {
methodOne: (...params) => this.methodOne(...params),
methodTwo: (...params) => this.methodTwo(...params)
}
}}
>
{children}
</ContainerContext.Provider>
)}}
Wrap your App with the provider.
import ContainerProvider from './ContainerProvider'
<ContainerProvider>
<App />
</ContainerProvider>
Then create a consumer for the context
export default function withContainer(InComponent) {
return function ContainerComponent(props) {
return (
<ContainerContext.Consumer>
{({ container }) => <InComponent {...props} container={container} />}
</ContainerContext.Consumer>
);
};
}
Then import the consumer and user in your components and you will get the methods as props
import withContainer from './ContainerConsumer'
render() {
const { container } = this.props;
return(<div />)
}
export default withContainer(YourComponent);
I'm importing a class from another script in my main React App, and would like to access a variable within that class from the main App. Basically the user types something into a textbox, then clicks a button to add that value to a variable. In the main App I import that class, then have another button to print those values (selectedvalues). I'm not entirely sure how to do it, but this is my code so far:
Class I am importing:
import React, { Component } from 'react';
class MyModule extends Component {
constructor() {
super();
this.state = {
selectedValues: '',
}
}
addValue() {
this.selectedValues += document.getElementById('textBox1').value + ', '
return this.selectedValues
}
render() {
return(
<div>
<input type='text' id='textBox1' />
<button onClick={() => this.addValue()}>Add Value</button>
</div>
)
}
}
export default MyModule
And where I would like to actually access that value
import React, { Component } from 'react';
import MyModule from './myModule.js'
class App extends Component {
constructor() {
super();
this.state = {
}
}
printValues() {
console.log(document.getElementById('themodule').selectedvalues)
}
render() {
return(
<MyModule id='themodule' />
<button onClick={() => printValues()}>Print values</button>
)
}
}
export default App
Is there a way I can do this?
Thanks!
Edit JS-fiddle here https://jsfiddle.net/xzehg1by/9/
You can create Refs and access state and methods from it. Something like this.
constructor() {
this.myRef = React.createRef();
}
render() { ... <MyModule id='themodule' ref={this.myRef} /> }
printValues() {
console.log(this.myRef)
}
more info here https://reactjs.org/docs/refs-and-the-dom.html
Basically, your state (selectedValues) has to go one level up in the React tree. You have to declare it as App's state, and then pass it down to MyModule via props.
Btw in addValue(), you're not changing any state. And this.selectedValues will be undefined. It's this.state.selectedValues, and this.props.selectedValues once you correct your code.
I think you should first read all react concepts and then start working on it. Anyhow i am modifying your code in one way to get your desired functionality but remember this is not best practice you have to use Redux for this kind of features
import React, { Component } from 'react';
class MyModule extends Component {
constructor() {
super(props);
this.state = {
inputValue : ''
};
this.handleInput = this.handleInput.bind(this);
this.addValue = this.addValue.bind(this)
}
handleInput(e){
this.setState({
inputValue : e.target.value
})
}
addValue() {
this.props.addValue(this.state.inputValue);
}
render() {
return(
<div>
<input type='text' id='textBox1' onChange={handleInput} />
<button onClick={this.addValue}>Add Value</button>
</div>
)
}
}
export default MyModule
and your main component should be
import React, { Component } from 'react';
import MyModule from './myModule.js'
class App extends Component {
constructor() {
super(props);
this.state = {
selectedValues : ''
};
this.printValues = this.printValues.bind(this);
this.addValues = this.addValues.bind(this);
}
printValues() {
console.log(this.state.selectedValues);
}
addValues(val){
this.setState({
selectedValues : this.state.selectedValues + " , "+val
})
}
render() {
return(
<React.Fragment>
<MyModule addValue={this.addValues}/>
<button onClick={this.printValues} >Print values</button>
</React.Fragment>
)
}
}
export default App
This should do your work
Let say I have this Parent
const Parent = () => <ChildComponent foo={<Button>clic</Button>} />
why would this code work
class ChildComponent extends React.Component {
render() {
return (
<div>
{this.props.foo}
</div>
)
}
}
but this code would not ?
class ChildComponent extends React.Component {
constructor(props) {
super(props)
const ParentButton = this.props.foo
}
render() {
return (
<div>
<ParentButton />
</div>
)
}
}
I need something like the second example in order to add some event to ParentButton.
I'd like to make this example work with class defined component
Update :
Based on answer I now have a partial solution
class ChildComponent extends React.Component {
constructor(props) {
super(props)
this.ParentButton = this.props.foo
}
render() {
return (
<div>
{this.ParentButton}
</div>
)
}
}
You're not assigning ParentButton to the ChildComponent.
What you currently have is a const floating in the constructor since const, let and var keywords are function/block scoped.
this. ParentButton = this.props.foo and succinctly <this. ParentButton > in your render function will get you what you're after.
I am trying to generate a component dynamically and render the component as a return from a function.
import React, { Component } from 'react';
import HelloWorld from './helloWorld';
export default class BaseComponent extends Component {
constructor(props) {
super(props)
this.getFields = this.getFields.bind(this)
}
getFields() {
let temp = { hi: 'Hello', world: 'World!' }
const test = temp.map(function(val, i) {
return <HelloWorld key={i} val={val} />
})
return test
}
render() {
return (
<div className="container">
{this.getFields}
</div>
);
}
}
But this function is not being invoked unless I use {this.getFields()} in my render method. Why can't I just use {this.getFields}, as that is bound in the constructor and hence should render the value. What am I missing?
You need to call the method from render function to use the returned value and not assign it and hence you need {this.getFields()}
render() {
return (
<div className="container">
{this.getFields()}
</div>
);
}
You need to invoke the function:
{this.getFields()}
I have two components. I want to call a method of the first component from the second component. How can I do it?
Here is my code.
First Component
class Header extends React.Component{
constructor(){
super();
}
checkClick(e, notyId){
alert(notyId);
}
}
export default Header;
Second Component
class PopupOver extends React.Component{
constructor(){
super();
// here i need to call Header class function check click....
// How to call Header.checkClick() from this class
}
render(){
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default PopupOver;
You can do something like this
import React from 'react';
class Header extends React.Component {
constructor() {
super();
}
checkClick(e, notyId) {
alert(notyId);
}
render() {
return (
<PopupOver func ={this.checkClick } />
)
}
};
class PopupOver extends React.Component {
constructor(props) {
super(props);
this.props.func(this, 1234);
}
render() {
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default Header;
Using statics
var MyComponent = React.createClass({
statics: {
customMethod: function(foo) {
return foo === 'bar';
}
},
render: function() {
}
});
MyComponent.customMethod('bar'); // true
Well, actually, React is not suitable for calling child methods from the parent. Some frameworks, like Cycle.js, allow easily access data both from parent and child, and react to it.
Also, there is a good chance you don't really need it. Consider calling it into existing component, it is much more independent solution. But sometimes you still need it, and then you have few choices:
Pass method down, if it is a child (the easiest one, and it is one of the passed properties)
add events library; in React ecosystem Flux approach is the most known, with Redux library. You separate all events into separated state and actions, and dispatch them from components
if you need to use function from the child in a parent component, you can wrap in a third component, and clone parent with augmented props.
UPD: if you need to share some functionality which doesn't involve any state (like static functions in OOP), then there is no need to contain it inside components. Just declare it separately and invoke when need:
let counter = 0;
function handleInstantiate() {
counter++;
}
constructor(props) {
super(props);
handleInstantiate();
}
You could do this to call a method of the child component from the parent component.
import React from 'react';
class Header extends React.Component {
constructor() {
super();
this.childComponentRef;
}
getChildComponent = (childComponent) => {
this.childComponentRef = childComponent;
this.childComponentRef.sayHi();
}
render() {
return (
<ChildComponent getChildComponent={this.getChildComponent} />
)
}
};
class ChildComponent extends React.Component {
componentDidMount () {
this.props.getChildComponent(this);
}
sayHi = () => {
alert("hi");
}
render() {
return (
<div className="displayinline col-md-12 ">
Hello
</div>
);
}
}
export default Header;