Вже є кілька чудових відповідей, але я не думаю, що їх пояснили не дуже добре, і кілька наведених методів містять деякі прийоми, які можуть відключити людей. Тому я перейду три основні способи (плюс один поза тематичний варіант), щоб зробити це і пояснити плюси і мінуси. Я в основному пишу це, тому що варіант 1 був рекомендований дуже багато, і є багато потенційних проблем із цим варіантом, якщо він не використовується правильно.
Варіант 1: Умовна візуалізація в батьківському.
Мені цей метод не подобається, якщо ви лише збираєтеся винести компонент один раз і залишити його там. Проблема полягає в тому, що він спричинить реакцію на створення компонента з нуля щоразу, коли ви перемикаєте видимість. Ось приклад. LogoutButton або LoginButton умовно відображаються в батьківському LoginControl. Якщо запустити це, ви помітите, що конструктор викликає кожен натискання кнопки. https://codepen.io/Kelnor/pen/LzPdpN?editors=1111
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Зараз React досить швидко створює компоненти з нуля. Однак він все одно повинен викликати ваш код під час його створення. Тож якщо ваш конструктор, компонентDidMount, візуалізація та ін кодується дорого, то він значно сповільнить показ компонента. Це також означає, що ви не можете використовувати це зі стаціонарними компонентами, де ви хочете, щоб стан зберігався, коли його заховано (і відновлено при відображенні). Так приховані компоненти не затримуватимуть початкове завантаження сторінки. Можуть також бути випадки, коли ви хочете, щоб стан компонента був скинутий під час переключення. У такому випадку це найкращий варіант.
Варіант 2: Умовна подача у дитини
Це створює обидва компоненти один раз. Потім замикайте решту коду візуалізації, якщо компонент прихований. Ви також можете коротко замикати іншу логіку в інших методах, використовуючи видиму опору. Зверніть увагу на console.log на сторінці кодування. https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
<LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
<LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
if(!this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
if(this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
Тепер, якщо логіка ініціалізації швидка, а діти без громадянства, ви не побачите різниці в продуктивності та функціональності. Однак навіщо змусити React створювати абсолютно новий компонент у кожному режимі? Якщо ініціалізація є дорогою, Варіант 1 запускатиме її кожен раз, коли ви перемикаєте компонент, який уповільнює сторінку при переключенні. Варіант 2 запустить усі вкладиші компонента при завантаженні першої сторінки. Уповільнення першого навантаження. Слід зазначити ще раз. Якщо ви просто показували компонент один раз на основі умови, а не перемикаєте його, або хочете його скинути під час toggglem, тоді варіант 1 - це добре і, мабуть, найкращий варіант.
Якщо повільне завантаження сторінки є проблемою, це означає, що у вас є дорогий код у способі життєвого циклу, і це, як правило, не гарна ідея. Ви можете, і, ймовірно, повинні вирішити повільне завантаження сторінки, перемістивши дорогий код із методів життєвого циклу. Перемістіть його до функції асинхронізації, яку розпочав ComponentDidMount, і зворотний виклик поставить її у змінну стану з setState (). Якщо змінна стану є нульовою, і компонент видно, тоді функція візуалізації повертає заповнювач. В іншому випадку надайте дані. Таким чином сторінка швидко завантажиться та заповнить вкладки під час завантаження. Ви також можете перенести логіку в батьківський і висувати результати дітям як реквізит. Таким чином ви можете визначити пріоритет, які вкладки завантажуються першими. Або кешуйте результати і виконайте лише логіку при першому появі компонента.
Варіант 3: Приховування класу
Заховання класів, мабуть, найлегше здійснити. Як згадувалося, ви просто створюєте клас CSS з дисплеєм: жоден та призначаєте клас на основі опори. Мінус - це весь код кожного прихованого компонента, який називається, і всі приховані компоненти прикріплені до DOM. (Варіант 1 взагалі не створює приховані компоненти. І варіант 2 короткого замикання непотрібний код, коли компонент прихований і повністю видаляє компонент з DOM.) Це здається, що це швидше при зміні видимості згідно з деякими тестами, зробленими коментаторами на інші відповіді, але я не можу з цим говорити.
Варіант 4: Один компонент, але змініть реквізити. А може взагалі немає компонента та кешувати HTML.
Цей не працюватиме для кожної програми, і це поза темою, оскільки мова не йде про приховування компонентів, але це може бути кращим рішенням для деяких випадків використання, ніж приховування. Скажімо, у вас є вкладки. Можливо, можливо, написати один Реактивний компонент і просто скористатися реквізитом, щоб змінити те, що відображається на вкладці. Ви також можете зберегти JSX у змінних стану та використовувати опору, щоб вирішити, який JSX повернути у функції візуалізації. Якщо JSX повинен бути згенерований, то зробіть це і кешуйте його в батьківському і надішліть правильний у якості опори. Або генеруйте в дитині та кешуйте її в стані дитини та використовуйте реквізит для вибору активного.