Как я могу передать состояние методу рендеринга вкладки в semantic ui react?

#javascript #reactjs #semantic-ui

#javascript #reactjs #semantic-ui

Вопрос:

Я использую Tab из SUIR, я пытаюсь передать некоторые данные о состоянии в одну из «панелей» и использовать <Dropdown> модуль для рендеринга этих данных о состоянии. Мне нужно передавать через props или что-то еще?

Я хочу отобразить выпадающий список, специфичный для Tab 2 . Мне действительно просто интересно, как передать данные о состоянии методу рендеринга панелей. Я подумал, может быть, переместить метод рендеринга из panes = [{},{},{}] и поместить его в render() из App . Я не уверен, что здесь лучший подход.

Codesandbox приведенного ниже кода.

 const panes = [
  { menuItem: "Tab 1", render: () => <Tab.Pane>Tab 1 Content</Tab.Pane> },
  { menuItem: "Tab 2", render: () => <Tab.Pane>Tab 2 Content</Tab.Pane> },
  { menuItem: "Tab 3", render: () => <Tab.Pane>Tab 3 Content</Tab.Pane> }
];

const MockAdapter = require("axios-mock-adapter");
const mock = new MockAdapter(axios);

mock.onGet("/dataschemas").reply(200, {
  data: [
    {
      id: "2",
      selfUri: "/dataschemas/2",
      type: "DataSchema",
      name: "Book Catalog"
    },
    {
      id: "3",
      selfUri: "/dataschemas/3",
      type: "DataSchema",
      name: "Business Articles"
    }
  ]
});

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { activeIndex: 1, dataschemas: [], dataSchemaName: "" };
  }

  handleRangeChange = e => this.setState({ activeIndex: e.target.value });
  handleTabChange = (e, { activeIndex }) => this.setState({ activeIndex });

  async componentDidMount() {
    await this.getSchemas();
  }

  getSchemas = async () => {
    try {
      const { data } = await axios.get("/dataschemas");
      console.log(data);
      const dataschemas = data.data;

      this.setState({ dataschemas: dataschemas });

      console.log("This is the dataschema list:", dataschemas);
    } catch (error) {
      console.error(Error(`Error fetching results list: ${error.message}`));
    }
  };

  handleSchemaChange = e => {
    //handle data schema dropdown change
  };

  // Example of dropdown using dataschemas state

  render() {
    const { activeIndex, dataschemas, dataSchemaName } = this.state;

    return (
      <div>
        <div>activeIndex: {activeIndex}</div>
        <input
          type="range"
          max="2"
          value={activeIndex}
          onChange={this.handleRangeChange}
        />
        <Tab
          panes={panes}
          activeIndex={activeIndex}
          onTabChange={this.handleTabChange}
        />
        <Dropdown
          placeholder="Select data schema"
          scrolling
          clearable
          fluid
          selection
          search
          noResultsMessage="Try a different Search"
          multiple={false}
          options={dataschemas.map(schema => {
            return {
              key: schema.id,
              text: schema.name,
              value: schema.name
            };
          })}
          header="PLEASE SELECT A DATASCHEMA"
          value={dataSchemaName}
          onChange={this.handleSchemaChange}
          required
        />
      </div>
    );
  }
}
  

Ответ №1:

Например, я могу придумать следующие решения:

  1. Глядя на ваш макет, я думаю, что нет необходимости передавать состояние методам рендеринга панелей, поскольку у вас есть Dropdown компонент вне его. Таким образом, вы можете просто определить параметры, Dropdown основанные на activeIndex значении.
  2. Если вы хотите переместить Dropdown компонент внутри содержимого вкладки (что имеет смысл), то вы можете

    • Создайте отдельные компоненты для содержимого каждой вкладки ( TabContent1 , TabContent2 и т.д. — конечно, можете подобрать более подходящие имена), А затем создайте panes внутри render() , как вы предложили:

       const panes = [
        { menuItem: "Tab 1", render: () => <TabContent1 {/* can pass props here */} /> },
        { menuItem: "Tab 2", render: () => <TabContent2 /> },
        { menuItem: "Tab 3", render: () => <TabContent3 /> }
      ]
        

      И вы можете дополнительно передать некоторые реквизиты этим компонентам, если хотите.
      Теперь, если содержимое вкладок очень похоже, вы можете создать его
      общий TabContent компонент и просто передать туда реквизиты будут отличаться, например dropdownOptions={...}

    • То же, что и в предыдущем примере, но вместо создания нового компонента (если вы считаете, что это слишком суетно) просто создайте отдельный renderTabContent() метод, а также создайте panes в render() таком:

       const panes = [
        { menuItem: "Tab 1", render: () => this.renderTabContent(
          /* can pass something here as well */
        )},
        { menuItem: "Tab 2", render: () => this.renderTabContent() },
        { menuItem: "Tab 3", render: () => this.renderTabContent() }
      ]
        

      Опять же, вы можете передать что-то этому методу, например dropdownOptions , чтобы заставить каждый из них возвращать разное содержимое. Или вы можете создавать разные renderTabContent1 , renderTabContent2 и т.д. Для содержимого каждой вкладки. Внутри этих методов вы можете легко получить доступ this.state

Это пример CodeSandbox с решением # 2. Я создал только один Tab2Content компонент, но я верю, что вы сможете подхватить идею и реализовать другие компоненты 👍

Комментарии:

1. Каждая вкладка будет отображать что-то совершенно другое, поэтому я думаю, что 3 отдельных компонента были бы лучшим подходом на самом деле. Не могли бы вы, возможно, предоставить краткую правку для песочницы, отображающей одно из ваших решений, чтобы я мог пометить это как правильное?

2. Конечно, без проблем

3. Обновлен ответ

4. Возможно, это быстрое решение, но что, если мне нужно несколько выпадающих списков на одной вкладке, добавить ли мне еще один <Dropdown> модуль внутри Tab2Content компонента? Или добавить другой объект в dropdownOptions при рендеринге main? codesandbox.io/s/6nvp9j20nr

5. Я добавил dropdownOptions в свой codesandbox просто в качестве примера на случай, если несколько ваших TabContents имеют похожий контент (извините, это, по-видимому, было непонятно). Так что нет необходимости создавать 3 разных компонента TabContent, а только один, для которого вы предоставляете разные параметры выпадающего списка. Но если вы собираетесь использовать разное содержимое под каждой вкладкой, тогда вы создаете отдельные компоненты TabContent для каждой вкладки без dropdownOptions реквизитов, поскольку в этом случае такой реквизит имеет мало смысла. Таким образом, вы можете определить там несколько Dropdown компонентов и сохранить параметры / значения внутри Tab2Content