#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:
Например, я могу придумать следующие решения:
- Глядя на ваш макет, я думаю, что нет необходимости передавать состояние методам рендеринга панелей, поскольку у вас есть
Dropdown
компонент вне его. Таким образом, вы можете просто определить параметры,Dropdown
основанные наactiveIndex
значении. -
Если вы хотите переместить
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/6nvp9j20nr5. Я добавил
dropdownOptions
в свой codesandbox просто в качестве примера на случай, если несколько ваших TabContents имеют похожий контент (извините, это, по-видимому, было непонятно). Так что нет необходимости создавать 3 разных компонента TabContent, а только один, для которого вы предоставляете разные параметры выпадающего списка. Но если вы собираетесь использовать разное содержимое под каждой вкладкой, тогда вы создаете отдельные компоненты TabContent для каждой вкладки безdropdownOptions
реквизитов, поскольку в этом случае такой реквизит имеет мало смысла. Таким образом, вы можете определить там несколькоDropdown
компонентов и сохранить параметры / значения внутриTab2Content