传递处理程序导致未定义

时间:2017-08-25 07:41:51

标签: javascript reactjs

我似乎无法正确传递此处理程序。 TabItem最终以onClick为未定义。

SearchTabs

export default class SearchTabs extends Component {
constructor(props) {
    super(props)
    const breakpoints = {
      [SITE_PLATFORM_WEB]: {
        displayGrid: true,
        autoFocus: true,
      },
      [SITE_PLATFORM_MOBILE]: {
        displayGrid: false,
        autoFocus: false,
      },
    };

    this.state = {
      breakpoints,
      filters: null,
      filter: null,
      isDropdownOpen: false,
      selectedFilter: null,
      tabs: null,
    };

    this.tabChanged = this.tabChanged.bind(this);
    this.closeDropdown = this.closeDropdown.bind(this);
  }
  ... more code

    createTabs(panels) {
        if(!panels) return;
        const tabs = panels.member.map((panel, idx) => {

          const { selectedTab } = this.props;
          const { id: panelId, headline } = panel;
          const url = getHeaderLogo(panel, 50);
          const item = url ? <img src={url} alt={headline} /> : headline;

          const classname = classNames([
            searchResultsTheme.tabItem,
            (idx === selectedTab) ? searchResultsTheme.active : null,
          ]);

          this.renderFilters(panel, idx, selectedTab);

          return (
            <TabItem
              key={panelId}
              classname={classname}
              idx={idx}
              content={item}
              onClick={this.tabChanged(idx, headline)}
            />
          );
        });

        return tabs;
      }

      tabChanged(idx, headline) {
        const { selectedTab } = this.props;
        const { selectedFilter } = this.state;
        const selectedFilterIdx = _.get(selectedFilter, 'idx', null);
        if (selectedTab !== idx) {
          this.props.resetNextPage();
          this.props.setTab(idx, selectedFilterIdx, headline);
          this.closeDropdown();
        }
      }
  render() {
    // const { panels, selectedTab } = this.props;
    // if (!panels || panels.length === 0) return null;
    //
    //
    // const { tabs, selectedTab } = this.props;

    return (
      <div>
        <ul>{this.state.tabs}</ul>
      </div>
    );
  }
}

export const TabItem = ({ classname, content, onClick, key }) => (
      <li key={key} className={`${classname} tab-item`} onClick={onClick} >{content}</li>
    );

所以在 TabItem onClick={onClick}中以未定义结束onClick。

更多信息

这是以前的工作原理,当这是父容器中的一个函数时:

// renderDefaultTabs() {
  //   const { panels, selectedTab } = this.props;
  //
  //   if (!panels || panels.length === 0) return;
  //
  //   let filter = null;
  //
  //   const tabs = panels.member.map((panel, idx) => {
  //     const { id: panelId, headline } = panel;
  //     const url = getHeaderLogo(panel, 50);
  //     const item = url ?
  //       <img src={url} alt={headline} /> : headline;
  //     const classname = classNames([
  //       searchResultsTheme.tabItem,
  //       (idx === selectedTab) ? searchResultsTheme.active : null,
  //     ]);
  //
  //     filter = (idx === selectedTab) ? this.renderFilters(panel) : filter;
  //
  //     return (
  //       <li
  //         key={panelId}
  //         className={classname}
  //         onClick={() => {
  //           this.tabChanged(idx, headline);
  //         }}
  //       >
  //         {item}
  //       </li>
  //     );
  //   });

所以我将其提取到了SearchTabs,包括将 tabChange d方法移动到我的新SearchTabs组件。现在在容器中,上面现在这样做了:

  renderDefaultTabs() {
    const {
      onFilterClick,
      panels,
      resetNextPage,
      selectedTab,
      selectedFilter,
      isDropdownOpen,
    } = this.props;

    return (<SearchTabs
      panels={panels}
      ...
    />);
  }

注意:renderDefaultTabs()作为prop发送到容器的render()中,Search调用它,因此在Search的render()中呈现它:

容器

render() {
    return (
      <Search
        request={{
          headers: searchHeaders,
          route: searchRoute,
        }}
        renderTabs={this.renderDefaultTabs}
        renderSearchResults={this.renderSearchResults}
        handleInputChange={({ input }) => {
          this.setState({ searchInput: input });
        }}
        renderAltResults={true}
      />
    );
  }

搜索是我们的应用使用的共享组件。

更新

所以我提到Container的render()将renderDefaultTabs函数作为道具传递给<Search />。在<Search />内,它最终执行此操作:render() { <div>{renderTabs({searchResults})}</div>}调用容器的renderDefaultTabs函数,如上所示,最终呈现

Update

所以它将它作为一个函数传递。当我单击一个TabItem时,它只是奇怪,它没有点击我的tabChanged函数

更新

基督,它正在击中我的标签。呃..我想我很好。谢谢大家!

1 个答案:

答案 0 :(得分:0)

onClick={this.tabChanged(idx, headline)}

这不是将函数传递给子组件props的正确方法。这样做(虽然不推荐)

onClick={() => this.tabChanged(idx, headline)}

<强>更新

我想补充更多解释。到onClick={this.tabChanged(idx, headline)},您正在执行tabChanged并将其返回值传递给onClick

使用之前的实施:onClick={() => { this.tabChanged(idx, headline); }},现在onClick将是一个类似于以下内容的函数:

onClick = {(function() {
  this.tabChanged(idx, headline);
})}

因此它适用于您之前的实现。 通过新的实施,onClick={() => this.tabChanged(idx, headline)}应该可以正常工作