2

I have simple component called List which is a simple ul with some li inside. Each li is a simple component. I have other parent component which render one input field and the List component. Tapping on Send key I catch text of input field. I want to call for example a function called handleNewText(inputText) but this function need to stay inside List component because the state I use to populate other li components live in List component.

I don' t want to refactor List and MyParent component passing the manage of data from List to MyParent.

first is parent and second is child

class TodoComp extends React.Component {
  constructor(props){
    super(props);
    this.handleKeyPress = this.handleKeyPress.bind(this);
  }

  componentDidMpunt(){
    console.log(this._child.someMethod());
  }


  handleKeyPress(event){
    if(event.key === 'Enter'){
      var t = event.target.value;

    }
  }

  render(){
    return (
        <div>
          <input
            className="inputTodo"
            type="text"
            placeholder="want to be an hero...!"
            onKeyPress={this.handleKeyPress}
          />
          <List/>
        </div>
    );
  }

}


export default class List extends React.Component {
  constructor() {
    super();
    this.flipDone = this.flipDone.bind(this);
    this.state = {
      todos: Array(3).fill({ content: '', done: false})
    };
  }

  flipDone(id) {
    let index = Number(id);

    this.setState({
      todos: [
        ...this.state.todos.slice(0, index),
        Object.assign({}, this.state.todos[index], {done: !this.state.todos[index].done}),
        ...this.state.todos.slice(index + 1)
      ]
    });
  }

  render() {

    const myList = this.state.todos.map((todo, index) => {
      return (
        <Todo key={index}
              clickHandler={this.flipDone}
              id={index}
              todo={todo}
              handleText={this.handleText}
        />
      );
    })

    return (
      <ul className="list">
        {myList}
      </ul>
    );
  }


ReactDOM.render(<TodoComp />,document.getElementById('myList'));

2
  • Can you show your code ? Commented Oct 25, 2016 at 8:50
  • Possible duplicate of Call child method from parent Commented Sep 3, 2019 at 7:24

3 Answers 3

6

You need to make use of refs to call a function in the child component from the parent component

render the List component from parent as

<List ref="myList"/>

and then access the handleNewText() function as this.refs.myList.handleNewText()

UPDATE:

Strings refs are no longer recommended by React, you should rather use ref callbacks, check this

<List ref={(ref) => this.myList=ref}/>

and then access the child function like

this.myList.handleNewText()
Sign up to request clarification or add additional context in comments.

Comments

1

Adding to @shubham-khatri solution:

If you are referencing a connected child component...

a. That child must say withRef: true in the (4th) config parameter:

@connect(store => ({
    foo: store.whatever
    …
}),null,null,{ withRef: true })

b. Access is through getWrappedInstance() (note, that getWrappedInstance also needs to be called ())

getWrappedInstance().howdyPartner()

Comments

0

I started learning React when functional component came out. Another way I experimented with some success is returning functions that you want to access as closures within a JSON. I like this method because closure is a construct of Javascript and it should still work even if React is updated yet again. Below is an example of child component

function Child(){
    //declare your states and use effects
    const [ppp, setPPP] = useState([]);
    const [qqq, setQQQ] = useState(2);
    //declare function that you want to access
    function funcA(){ /*function to interact with your child components*/}
    function funcB(){ /*function to interact with your child components*/}

    //pure React functional components here
    function Content(){
         //function that you cannot access
         funcC(){ /*.....*/}
         funcD(){/*.......*/}
         //what to render
         return (
           <div> 
               {/* your contents here */} 
           </div>
         )
    }
    //return accessible contents and functions in a JSON
    return {
        content: Content, //function for rendering content
        ExposeA: funcA,   //return as a closure
        ExposeB: funcB,   //return as a closure
    }
}

Below is an example of how you would render the child contents within the parent

function Parent(){
    let chi = Child();
    let ChildContent = chi.Content;
    //calling your exposed functions
    //these function can interacts with the states that affects child components
    chi.ExposeA();  
    chi.ExposeB();
    //render your child component
    return (<div>
        <div> {/* parent stuff here */</div>
        <div> {/* parent stuff here */</div>
        <ChildContent {/*Define your props here */} />
    </div>)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.