简体   繁体   中英

Passing down multiple methods within single prop React.js

I have a react.js component where I want to pass down a bunch of different methods to child components from the parent component, the methods modify the state of the parent component.

class Page extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: this.props.items,
      currentItemID: 1
    };

    this.actions = this.actions.bind(this);
  }

  render() {
    return (
      <div className="page">
        {
          this.state.items.map(item =>
            <Item key={item._id} item={item} actions={this.actions} />
          )
        }
      </div>
    );
  }

  actions() {
    return {
      insertItem: function (itemID) {
        const currentItems = this.state.items;
        const itemPosition = this.state.items.map((item) => item._id).indexOf(itemID);

        const blankItem = {
          _id: (new Date().getTime()),
          content: ''
        };

        currentItems.splice(itemPosition + 1, 0, blankItem)

        this.setState({
          items: currentItems,
          lastAddedItemID: blankItem._id
        });
      },
      setCurrentItem: function (itemID) {
        this.setState({ currentItemID: itemID });
      },
      focus: function(itemID) {
        return (itemID === this.state.currentItemID);
      }
    }
  }

In my child component, I am trying to use the focus method in the componentDidMount lifecyle method as shown below:

 componentDidMount() {
    if (this.props.actions().focus(this.props.item._id)) {
      this.nameInput.focus();
    }
  }

However, I am getting the error

Uncaught TypeError: Cannot read property 'currentItemID' of undefined

in the definition of the focus method, within the actions methods. Can anyone point me in the right direction as to why I'm getting the error or an alternative way to pass down multiple actions to child components?

the context is not passed to the function, then the 'this' in the function is that of the function itself and not the component.. you can solve it that way (put the functions in the components):

      actions() {
         return {
            insertItem: this.insertItem.bind(this),
            setCurrentItem: this.setCurrentItem.bind(this),
            focus: this.focus.bind(this),
         }
      }
      insertItem(itemID) {
        const currentItems = this.state.items;
        const itemPosition = this.state.items.map((item) => item._id).indexOf(itemID);

        const blankItem = {
          _id: (new Date().getTime()),
          content: ''
        };

        currentItems.splice(itemPosition + 1, 0, blankItem)

        this.setState({
          items: currentItems,
          lastAddedItemID: blankItem._id
        });
      },
      setCurrentItem(itemID) {
        this.setState({ currentItemID: itemID });
      },
      focus(itemID) {
        return (itemID === this.state.currentItemID);
      }

but yet, the recomended way is to put the functions in the components like above and remove the actions method and do this:

<Item key={item._id} item={item} actions={{
            insertItem: this.insertItem.bind(this),
            setCurrentItem: this.setCurrentItem.bind(this),
            focus: this.focus.bind(this)
        }} />

or

<Item key={item._id} item={item} actions={{
            insertItem: () => this.insertItem(),
            setCurrentItem: () => this.setCurrentItem(),
            focus: () => this.focus()
        }} />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM