Передача компонента в качестве реквизита и его использование в событии

#reactjs #react-props

#reactjs #react-props

Вопрос:

Я создаю навигацию в стиле вкладок. И я передал вкладки и их содержимое как дочерние элементы. Как показано ниже

 import "./App.css";
import Tabs from "./TranslationPopoverCardComponent/Tabs";

class App extends React.Component {
  render() {
    return (
      <div>
        <Tabs>
          <span label="Gator">
            <button>Butotn here</button>
          </span>
          <span label="Croc">
            After 'while, <em>Crocodile</em>!
          </span>
          <span label="Sarcosuchus">Nothing to see here,</span>
        </Tabs>
      </div>
    );
  }
}

export default App;
  

Внутри компонента Tabs.

 
class Tabs extends Component {
  constructor(props) {
    super(props);
    this.state = {
      //setting default open tab
      activeTab: this.props.children[0],
    };
    this.changeTab = this.changeTab.bind(this);
  }

  changeTab(e) {
    this.setState({ activeTab: e.target.value });
  }

  render() {
    const tabs = this.props.children.map((child) => {
      return (
        <span>
          <button value={child} onClick={this.changeTab}>  // this line here
            {child.props.label}
          </button>
        </span>
      );
    });
    return (
      <div>
        {tabs}
        <br />
        {this.state.activeTab}
      </div>
    );
  }
}

export default Tabs;
  

Вкладка по умолчанию и загружается, как и ожидалось, показывая кнопку. А затем, когда я нажимаю другую вкладку, текст не загружается. Показывает [объект Object] . Могу ли я не передавать props.children в качестве реквизита компонента, а затем устанавливать его как состояние через событие? (что я сделал не так?)

Я пробовал заменить эту строку там child на with child.props.children , но тогда компонент button не отображает и не показывает [object Object], а другие работают просто отлично.

Ответ №1:

проблема в том, что inputs/buttons значение не хранит объект, значение всегда является строкой, поэтому вы видите [object,object] при нажатии каждой кнопки вкладки (try console.log(typeof e.target.value)) .

кроме того, вам не нужно использовать значение, вместо этого вы можете передать дочерний элемент непосредственно в функцию следующим образом:

  <button onClick={() => setActive(child)}>
  

вот полный код

Ответ №2:

Используйте это в onClick

  onClick={() => this.changeTab(child)}
  

и измените обработчик как

   changeTab(e) {
    this.setState({ activeTab: e });
  }
  

Ответ №3:

Вы можете просто передать индекс, нажав на вкладку, т.е

 const tabs = this.props.children.map((child,i) => {
      return (
        <span>
          <button value={child} onClick={ () => this.changeTab(i)}> 
            {child.props.label}
          </button>
        </span>
      );
    });

  

и на вкладке изменения сделайте это:

 changeTab = (i) =>  {
    this.setState({ activeTab: this.props.children[i] });
  }

  

Вот полный код:

 import React from "react";
import "./styles.css";

class Tabs extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      //setting default open tab
      activeTab: this.props.children[0]
    };
    this.changeTab = this.changeTab.bind(this);
  }

  changeTab = (i) => {
    this.setState({ activeTab: this.props.children[i] });
  };

  render() {
    const tabs = this.props.children.map((child, i) => {
      return (
        <span>
          <button value={child} onClick={() => this.changeTab(i)}>
            {child.props.label}
          </button>
        </span>
      );
    });
    return (
      <div>
        {tabs}
        <br />
        {this.state.activeTab}
      </div>
    );
  }
}

export default function App() {
  return (
    <div className="App">
      <Tabs>
        <span label="Gator">
          <button>Button here</button>
        </span>
        <span label="Croc">
          After 'while, <em>Crocodile</em>!
        </span>
        <span label="Sarcosuchus">Nothing to see here,</span>
      </Tabs>
    </div>
  );
}


  

Вот демонстрация: https://codesandbox.io/s/cranky-kepler-sr4pz?file=/src/App.js:0-1081