Я искал ответ на этот вопрос - ближе всего я нашел этот вопрос - но есть, я думаю, существенная разница в моем случае (тот факт, что он начинает попадать в родительское владение) состояние его детей ... детей), которое в конечном итоге привело меня к просьбе дать некоторые разъяснения.
Ниже приведен очень простой пример того, что я имею в виду (и, надеюсь, лучше проиллюстрирует то, что я спрашиваю):
Предположим, у нас есть несколько книжных документов, таких как
bookList = [
{
title: "book 1",
author: "bob",
isbn: 1,
chapters: [
{ chapterNum: 1, chapterTitle: "intro", chapterDesc: "very first chapter", startPg: 2, endPg: 23 },
{ chapterNum: 2, chapterTitle: "getting started", chapterDesc: "the basics", startPg: 24, endPg: 45 }
]},
{
title: "book 2" ... }
]
Таким образом, главное, что эти встроенные объекты в документах могут быть очень длинными и, следовательно, могут быть свернуты / развернуты.
И вот примерный пример кода, показывающего компоненты
class App extends Component {
constructor(props) {
super(props);
this.state = {
books: bookList,
focusBook: null
}
this.updateDetailDiv = this.updateDetailDiv.bind(this);
}
updateDetailDiv(book) {
this.setState(
{ focusBook: book}
);
}
render() {
return(
<BookList
bookList = {this.state.books}
updateDetailDiv = { this.updateDetailDiv }
/>
<BookDetail
focusBook = { this.state.focusBook }
/>
);
}
}
const BookList = props => {
return (
props.bookList.map(item=>
<li onClick={()=> props.updateDetailDiv(item)}> {item.title} </li>
)
);
}
const BookDetail = props => {
return (
<div className="bookDetails">
{ props.focusBook != null
? <div>
{props.focusBook.title},
{props.focusBook.author},
{props.focusBook.isbn}
Chapters:
<div className="chapterList">
{ props.focusBook.chapters.map(item=>
<span onClick={()=>someFunction(item)}>{item.chapterNum} - {item.chapterName}</span>
)}
</div>
<div id="chapterDetails">
This text will be replaced with the last clicked chapter's expanded details
</div>
</div>
: <div>
Select A Book
</div>
})
}
someFunction(item) {
document.getElementById('chapterDetails').innerHTML = `<p>${item.chapterDesc}</p><p>${item.startPg}</p><p>${item.endPg}</p>`;
}
Так что моя проблема в том, что я не уверен, каков наилучший подход к работе с простой косметикой c / визуальные изменения данных в функциональных компонентах без сохранения состояния без передачи их родительскому компоненту - что хорошо и имеет смысл для первого ребенка - но что происходит, когда у многих детей будут свои собственные дети (у которых могут быть свои собственные дети) -> все требуют свои варианты рендеринга? Например, здесь компонент App будет повторно отображать компонент DetailDiv (поскольку состояние изменилось), но я не хочу, чтобы приложение также обрабатывало подробный div DetailDiv. В моем примере все очень просто, но само приложение, над которым я работаю, имеет 2 или 3 слоя встроенных элементов, которые - однажды отрендеренные App - могут реально визуально измениться обычным JS.
Так что в моем примере вы увидите, что у меня есть someFunction()
в каждом списке глав - я могу сделать эту работу, написав отдельную простую «традиционную JS DOM-функцию» (ie: target.getElementById
или closest()
- но я не думаю, что я должен использовать обычный JS для манипулирования DOM при использовании React.
Итак, еще раз, чтобы подвести итог - каков наилучший способ обработки простое манипулирование DOM для рендеринга вывода компонентов без состояния? Превращение их в их собственный класс кажется излишним - и «родительское» приложение обрабатывает своих «внуков», и состояние «правнуков» будет громоздким по мере роста приложения. Должно быть, пропущен очевидный пример, потому что я не видел много способов справиться с этим без слоев с состоянием компонентов.
EDIT для ясности:
BookDetail
- это компонент без сохранения состояния.
Родительский компонент с состоянием (App
) * передает объект как опору (*1031*)
. Когда состояние App
изменяется, он будет возвращаться снова, отражая изменения.
Предположим, BookDetail
отвечает за отображение большого количества данных.
Я хочу, чтобы каждый из span
в BookDetail
при нажатии, отобразит соответствующий item
в chapterDetail
div. Если щелкнуть по другому span
, то chapterDetail
div заполняется данными item
. (это всего лишь простой пример - это может быть любое другое чистое изменение внешнего вида для какого-либо компонента без состояния - когда кажется, что родитель должен излишне следить за ним)
Я не знаю, как изменить UI / внешний вид компонента без состояния после его рендеринга, не присваивая ему состояния, ИЛИ не заставляя родителя отслеживать то, что по сути является «подсостоянием» (поскольку единственный способ обновить внешний вид компонента - это изменить его состояние, вызывая рендер).
Есть ли способ сделать это, не делая BookDetail компонентом с состоянием?