Я пытаюсь обернуть один компонент другим и вызвать функцию из этого «одного» компонента.
<Parent>
<Child1>
<button
onClick = {
//toggleSomething
console.info("Run function `toggleSomething` from parent")
}
>
Change state 1
</button>
</Child1>
<Child2>
<button
onClick = {
//toggleSomething
console.info("Run function `toggleSomething` from parent")
}
>
Change state 2
</button>
</Child2>
</Parent>
а в родительском компоненте у меня есть:
class Parent extends React.Component {
state = {
something: false
};
toggleSomething = () => {
this.setState({
something: true
});
};
render() {
return <div className = "parentClasses">{this.props.children}</div>;
}
}
Вот площадка: https://codesandbox.io/s/1ykllwnyq3
Для этого есть решение?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


class App extends React.Component {
render() {
return (
<div>
<Parent>
<Child1 />
<Child2 />
</Parent>
</div>
);
}
}
class Parent extends React.Component {
state = {
something: false
};
toggleSomething = () => {
console.info("now toggling !!");
this.setState({
something: true
});
};
render() {
const reactChildren = React.Children.toArray(this.props.children);
const childrenWithProps = reactChildren.map(element =>
React.cloneElement(element, {
toggleSomething: this.toggleSomething
})
);
return <div className = "parentClasses">{childrenWithProps}</div>;
}
}
const Child1 = props => {
return (
<div class = "someClasses">
<button
onClick = {
//toggleSomething
() => {
props.toggleSomething();
console.info("Run function `toggleSomething` from parent");
}
}
>
Change state 1
</button>
</div>
);
};
const Child2 = props => {
return (
<div class = "someOtherClasses">
<button
onClick = {() => {
debugger;
props.toggleSomething();
console.info("Run function `toggleSomething` from button 2");
}}
>
Change state 2
</button>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id = "root"></div>.Now the content of Child 2 and Child1 can be rendered according to props let say tomorrow, you want something else for Child 2 view. you can change your child Component like this.
const Child2 = props => {
const { RenderView, toggleSomething } = props
//renderView is your view Component(stateless/statefull)
return (
<div class = "someOtherClasses">
{<RenderView toggleSomething = {toggleSomething} />}
</div>
);
};
Как насчет такого подхода?
Это не сработает, если я хочу иметь динамический контент внутри <Child1> и <Child2>.
Да, ты прав. Позвольте мне отредактировать ответ, используя другой подход, который вы можете сделать расширяемым. Проблема в том, что у вас есть контекст родительского компонента. вы не можете получить доступ к опоре, переданной там child1 или child2. Вам нужно написать это как другой компонент. И там вы можете иметь различные шаблоны
Этого все еще недостаточно. Он будет использоваться во многих местах, поэтому должен быть динамичным. Допустим, этот <Parent> - обертка, а <Child1> с <Child2> - стороны - левая и правая. Стандартным является то, что Child1 виден пользователю, а Child2 - нет. Если я нажму кнопку в Child1, состояние Parent должно измениться и добавить CSS, чтобы показать Child2 и скрыть Child1. У Child2 также есть кнопка с таким же действием, чтобы вы могли «двигаться вперед» и «назад». Например, нажмите «Забыли пароль» в Child1, и тогда появится Child2 с формой и кнопкой «вернуться» к Child1. Вот почему мне нужно использовать его как <Child1></Child1>
Прямо сейчас ваши Child1 и Child2 ничего не делают, только заполнитель. Вы просто возвращаете props.children. Вы можете визуализировать различные компоненты с разной логикой, передаваемой как RenderView из любого места в Child1 в упомянутом выше дизайне. Вы в основном получаете то же поведение ... Я не могу придумать, как это сделать без тех изменений, которые я сделал. Я уже упоминал в предыдущем комментарии, почему это невозможно. Спасибо
Вам нужно передать функцию и получить к ней доступ из props. Clone Element позволяет добавить опору всем дочерним элементам.
import React from "react";
import ReactDOM from "react-dom";
const Child1 = props => {
return <button onClick = {props.handler}>test</button>;
};
class Parent extends React.Component {
state = {
something: "nope"
};
toggleSomething = () => {
this.setState({
something: "yes"
});
};
render() {
const childrenWithProps = React.Children.map(
this.props.children, child =>
React.cloneElement(
child, { handler: this.toggleSomething }
)
);
return <div className = "parentClasses">
{this.state.something}
{childrenWithProps}
</div>;
}
}
const App = () =>
<Parent>
<Child1/>
</Parent>
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Проблема в том, что мне нужно передать содержимое в компонент <Child1>. Будет форма с кнопкой, и эта кнопка должна вызывать действие. Я бы использовал эти компоненты <Parent> и <Child1> в нескольких местах, поэтому они должны быть «динамическими».
Мой ответ: pastebin.com/ELekzcgQ В комментарии я не могу вставить код.
Принимая на себя ответственность за эти компоненты:
Parent: Береги состояние.Child1 и Child2: универсальный контейнер пользовательского интерфейса.App: Заботится о том, как отображается состояние Parent.Это можно сделать с помощью техники рендерить реквизит.
В приведенном ниже примере вместо передачи элемента в качестве дочернего элемента <Parent> используется вместо этого передается функция.
class App extends React.Component {
render() {
return (
<div>
<Parent>
{toggle => (
<React.Fragment>
<Child1>
<button onClick = {toggle}>Change state 1</button>
</Child1>
<Child2>
<button onClick = {toggle}>Change state 2</button>
</Child2>
</React.Fragment>
)}
</Parent>
</div>
);
}
}
class Parent extends React.Component {
state = {
something: false
};
toggleSomething = () => {
this.setState({
something: true
});
};
render() {
return (
<div className = "parentClasses">
{this.state.something.toString()}
{this.props.children(this.toggleSomething)}
</div>
);
}
}
const Child1 = props => {
return <div class = "someClasses">{props.children}</div>;
};
const Child2 = props => {
return <div class = "someOtherClasses">{props.children}</div>;
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);<script crossorigin src = "https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id = "root"></div>Вот и все. Прекрасно работает. Большое спасибо!
передайте свою функцию как реквизит дочернему элементу.