ReactJS calling functions from child component [duplicate] - javascript

I have a parent and child compoents and I want to call a parent method in the child component like this:
import Parent from './parent.js';
class Child extends React.Component {
constructor(props) {
super(props);
};
click() {
Parent.someMethod();
}
render() {
<div>Hello Child onClick={this.click}</>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
};
someMethod() {
console.log('bar');
}
render() {
<div>Hello Parent</>
}
}
This returns an error message:
Uncaught TypeError: _Parent2.default.someMethod is not a function
How can this parent method be called in the child component?

Try this. Passing the function down as props to the child component.
import Parent from './parent.js';
class Child extends React.Component {
constructor(props) {
super(props);
};
click = () => {
this.props.parentMethod();
}
render() {
<div onClick={this.click}>Hello Child</div>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
};
someMethod() {
console.log('bar');
}
render() {
<Child parentMethod={this.someMethod}>Hello Parent, {this.props.children}</Child>
}
}

You can try doing something like calling the function of parent by passing the state of your parent to the child and then call using the props in child class.
class FlatListItem extends Component{
constructor(props){
super(props)
}
render(){
return(
<TouchableOpacity style={styles.button}
onPress=
{(item)=>this.props.parentFlatlist.delete(item)}></TouchableOpacity>
</Swipeout>
)
}}
And now consider you have a parent class RandomList:
class RandomList extends Component{
static navigationOptions = ({navigation}) =>{
return{
headerTitle: 'Random List'
}
};
state = {
lists : [],
refreshing : false
}
constructor(props){
super(props)
}
delete= (item) =>{
//delete your item
console.log(item)
}
render(){
return(
<BackgroundImageComponent>
<FlatList
keyExtractor={item => item}
data = {this.state.lists}
renderItem = {({item,index}) => (
<FlatListItem onPress={()=>this.seeTheList(item)} item1={item} parentFlatList={this} index={index}>
</FlatListItem>
)}
/>
</ScrollView>
</BackgroundImageComponent>
)
}}export default RandomList
See here, I am passing parentFlatlist={this} and then would be using the same instance later in the child class.
The main idea is to focus upon the way I am able to render the delete function and not to focus upon the code. Forgive me if the code is misplaced or broken.

Related

How to correctly call function from component in another component

I saw a few similar questions, but about parent/child elements, i have that kind of node tree:
IndexPage -> Modals -> ClientDetails(it's modal component)
-> Header
I want to call ClientDetails.openModal inside Header, tried many ways like creating refs for ClientDetails in indexPage and then pass indexPage to header like prop, but it's works strange, i see refs of props.IndexPage, but when trying access refs directly it's underfind
class IndexPage extends React.Component {
constructor(props) {
super(props);
this.modals = React.createRef();
}
render() {
return (
<Layout>
<SEO/>
<Header indexPage={this}/>
<Story/>
<Products/>
<Clients/>
<Reviews/>
<Partners/>
<Footer/>
<Modals ref={this.modals} />
</Layout>
)
}
}
class Modals extends React.Component {
constructor(props) {
super(props);
this.clientDetailsRef = React.createRef();
}
render() {
return (
<>
<ThankYou/>
<ContactDetails ref={this.clientDetailsRef}/>
</>
)
}
}
class Header extends React.Component {
constructor(props) {
super(props);
this.state = { isActive: false, isSticky: false };
this.toggle = this.toggle.bind(this);
this.indexPage = props.indexPage
console.log(this.indexPage)
console.log(this.indexPage.modals)
}
}
I think you can solve your problem using react.js context.
You wanted to control the Modals component in the Header component. So you tried to reference the Modals component toggle function in the Header component to solve the problem.
I think it is a fine solution.
But in my opinion, sharing state in peer components is also another solution.
So you can use react.js context to share states between two peer components in a parent component of them. I think doing this is following react declarative programming.
Please check this code
Here is a small fiddle for calling a child function from the parent
https://jsfiddle.net/c1qfn9Lx/9/
class Modal extends React.Component {
constructor(props) {
super(props);
this.state= {
showModal: false
}
this.toggleModal = this.toggleModal.bind(this)
}
toggleModal() {this.setState({showModal: !this.state.showModal})}
render() {
const { showModal } = this.state;
return(
<div className="modal">
{showModal &&
<div>
Showing modal
</div>
}
</div>
)
}
}
class TodoApp extends React.Component {
constructor(props) {
super(props)
this.modalRef = React.createRef()
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.modalRef.current.toggleModal();
}
render() {
return (
<div className="parent">
<Modal ref={this.modalRef} />
<button onClick={this.handleClick}>Click</button>
</div>
)
}
}
ReactDOM.render(<TodoApp />, document.querySelector("#app"))
I would try doing this:
class IndexPage extends React.Component {
constructor(props) {
super(props);
this.state = {modalsRef: null};
}
render() {
return (
<Layout>
<SEO/>
<Header modalsRef={this.state.modalsRef}/>
<Story/>
<Products/>
<Clients/>
<Reviews/>
<Partners/>
<Footer/>
<Modals ref={r => !this.state.modalsRef && this.setState({modalsRef:r})} />
</Layout>
)
}
}
But please note: the property won't work in the constructor of Header most likely. It should work though by the time you're doing things like Button.onClick callbacks.

Passing state from child class to parent

I know that this is probably the most asked question about React, but none of the answers helped me.
I have 2 classes:
Child
class Preview extends Component {
constructor(...args) {
super(...args);
this.state = {
isCommentOpen: false
};
this.handleComment = ::this.handleComment;
render() {
return(
button type="button" onClick={this.handleComment}>Comment</button>
)}
handleComment(){
this.setState({isCommentOpen: !this.state.isCommentOpen});
}
export default Preview;
Parent
class Profile extends Component {
render(){
return(
<div>
<_.Preview />
//the place where I want to add validation from the component above
{this.state.isCommentOpen ? <span>Cool</span> : null}
</div>
}
You should not mutate or directly assign this.props as shown in the other answer:
this.props.isCommentOpen = !this.props.isCommentOpen // <-- DON'T DO THIS! 🎃
Instead, you should have a callback function to let the Parent component update the child component:
class Profile extends Component {
constructor(props) {
super(props);
this.state = {
isCommentOpen: false;
}
this.handleComment = this.handleComment.bind(this); // <-- important!
}
handleComment() {
this.setState({ isCommentOpen: !this.state.isCommentOpen });
}
render() {
return (
<div>
<Preview handleComment={this.handleComment} />
{ this.state.isCommentOpen ? <span>Cool</span> : null }
</div>
)
}
}
export default Profile
The child component then only needs to call this.props.handleComment:
// Child Component:
class Preview extends Component {
render() {
return(
<button type="button" onClick={this.props.handleComment}>Comment</button>
}
}
export default Preview;

How to pass state property to child component in constructor with React.js?

How to pass a state property of the father component as props for the child component in the constructor? I have something like this:
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
components: [
{ component: (
<ChildComponent
statusAsProps={this.state.status} />
)
}
]
};
}
render(){
return(
<div>{this.state.components[0].component}</div>
)
}
But shows me the error of this.state is undefined.
Is a way to bind "this" of the state as a prop for the children component?
You're using this.state inside itself before it is even defined and assigned a value. That's why the undefined. Avoid complexity and simply render the child component by passing in the required props from the parent's state.
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
};
}
render() {
return (
<div>
<ChildComponent statusAsProps={this.state.status} />
</div>
)
}
}
It is not a good idea to store components on the state. You can just define that in your render
class FatherComponent extends Component {
constructor(props) {
super(props);
this.state = {
status: true
};
}
render(){
return(
<div>
{ <ChildComponent statusAsProps={this.state.status} }
</div>
)
}
method

How to render an array of components (objects) with specific props in React?

problem in rendering an array of components. this is my pen a link. where you can see the result.
there should be 10 cards in result but it does not render them.
class Main extends React.Component {
constructor(props) {
super(props);
this.state={chng:0}
}
render() {
return (
<div>
<h1>Hello from Main!</h1>
<Card name="sample" />
<CardsHolder />
</div>
)
}
}
class Card extends React.Component {
constructor(props) {
super(props);
}
render() {
return (<div className="card">{this.props.name}</div>);
}
}
class CardsHolder extends React.Component {
constructor(props) {
super(props);
}
render() {
const cards=[];
axios.get('https://randomuser.me/api/?
results=10&inc=name,registered&nat=fr')
.then(json => json.data.results.map(result => (
cards.push(<Card key={result.name.first} name={result.name.first} />)
)))
console.log(cards)
// I think there is correct array of components in Console but it does not render them
return (<ul>{cards}</ul>)
}
}
ReactDOM.render(<Main />, document.getElementById('react-content'))
This will work, Notes to takes:
We do our AJAX requests in componentDidMount method so we can fire a render at the very top mount of our component using setState
While doing that thing, Dont store JSX in your component's state.
your code.

Can I modify a parent state of a component in ReactJs?

Let's say I'm having the following component:
class LeftPanel extends React.Component {
constructor(props) {
super(props);
this.state = {abc: 'xyz'};
}
render() {
return (
<div>
<Thumb src={img1}/>
<Thumb src={img2}/>
</div>);
}
Inside the component, there's an inner component called Thumb that goes like there:
class Thumb extends React.Component {
constructor(props) {
super(props);
this.state = { src: props.src };
}
render() {
return (
<div>
<img src={this.state.src}></img>
</div>
);
}
}
Question: Can I modify the state of LeftPanel Component inside Thumb? If yes, how?
create a method in Left panel to handle the event. Then pass the method to the child component.
Now if you want to pass data to the parent I would recommend a library like flux or redux. since redux has a global state it is accessible to all components. When you modify the global state to whole application is rerendered with the new state. The new state is visible by all components.
class LeftPanel extends React.Component {
constructor(props) {
super(props);
this.modifyLeftpanel = this.modifyLeftpanel.bind(this);
this.state = {abc: 'xyz'};
}
modifyLeftpanel(newvar){
//Do something with newvar
}
render() {
return (
<div>
<Thumb src={img1} modifyLeftPanel={this.modifyLeftpanel} />
<Thumb src={img2} modifyLeftPanel={this.modifyLeftpanel} />
</div>);
}
here is the thumb
class Thumb extends React.Component {
constructor(props) {
super(props);
this.state = { src: props.src };
this.doSomething = this.doSomething.bind(this);
}
doSomething(){
this.props.modifyLeftpanel(10);
}
render() {
return (
<div>
<img src={this.state.src}></img>
<button onClick={this.doSomething}>Modify Parent</button>
</div>
);
}

Categories

Resources