Dlaczego w poniższym przykładzie pseudokodu Child nie jest ponownie renderowany, gdy kontener zmienia foo.bar?
Container {
handleEvent() {
this.props.foo.bar = 123
},
render() {
return <Child bar={this.props.foo.bar} />
}
Child {
render() {
return <div>{this.props.bar}</div>
}
}
Nawet jeśli wywołam forceUpdate()
po zmodyfikowaniu wartości w Container, Child nadal pokazuje starą wartość.
javascript
html
reactjs
Tuomas Toivonen
źródło
źródło
<Route exact path="/user/:email" component={ListUserMessagePage} />
, łącze na tej samej stronie zaktualizuje właściwości bez tworzenia nowej instancji i uruchamiania zwykłych zdarzeń cyklu życia.Odpowiedzi:
Zaktualizuj element podrzędny, aby atrybut „klucz” był równy nazwie. Komponent będzie ponownie renderowany za każdym razem, gdy zmieni się klucz.
Child { render() { return <div key={this.props.bar}>{this.props.bar}</div> } }
źródło
key
wymagane, czy tylkosetState
? Mam dzieci, które polegają na stanie rodziców, ale nie uruchamiają ponownego renderowania ...Ponieważ dzieci nie wyrzekają się, jeśli zmieniają się właściwości rodzica, ale jeśli zmienia się jego STAN :)
Pokazujesz to: https://facebook.github.io/react/tips/communicate-between-components.html
Będzie przekazywać dane od rodzica do dziecka za pomocą właściwości, ale nie ma tam logiki ponownego renderowania.
Musisz ustawić stan dla rodzica, a następnie oddać dziecko w stanie zmiany rodzica. To mogłoby pomóc. https://facebook.github.io/react/tips/expose-component-functions.html
źródło
Miałem ten sam problem. To jest moje rozwiązanie, nie jestem pewien, czy to dobra praktyka, powiedz mi, jeśli nie:
state = { value: this.props.value }; componentDidUpdate(prevProps) { if(prevProps.value !== this.props.value) { this.setState({value: this.props.value}); } }
UPD: Teraz możesz zrobić to samo używając React Hooks: (tylko jeśli komponent jest funkcją)
const [value, setValue] = useState(propName); // This will launch only if propName value has chaged. useEffect(() => { setValue(propName) }, [propName]);
źródło
componentDidUpdate
tym przypadku znajduje się on w komponencie Child.FunctionComponents
nim automatycznie zaktualizuje komponenty potomne, jeśli zmienią się właściwości.Zgodnie z filozofią Reacta komponent nie może zmieniać swoich właściwości. powinny być otrzymane od rodzica i niezmienne. Tylko rodzic może zmieniać właściwości swoich dzieci.
ładne wyjaśnienie stanu kontra rekwizyty
przeczytaj też ten wątek Dlaczego nie mogę zaktualizować właściwości w pliku act.js?
źródło
Podczas tworzenia komponentów React z
functions
iuseState
.const [drawerState, setDrawerState] = useState(false); const toggleDrawer = () => { // attempting to trigger re-render setDrawerState(!drawerState); };
To nie działa
To działa (dodawanie klucza)
źródło
Potwierdzono, dodanie klucza działa. Przeszedłem przez doktorów, żeby spróbować i zrozumieć dlaczego.
React chce wydajnie tworzyć komponenty potomne. Nie wyrenderuje nowego komponentu, jeśli jest taki sam jak inny element podrzędny, co przyspiesza ładowanie strony.
Dodanie klucza wymusza reakcję na renderowanie nowego komponentu, resetując w ten sposób stan tego nowego komponentu.
https://reactjs.org/docs/reconciliation.html#recursing-on-children
źródło
Powinieneś użyć
setState
funkcji. Jeśli nie, stan nie zapisze twojej zmiany, bez względu na to, jak użyjesz forceUpdate.Container { handleEvent= () => { // use arrow function //this.props.foo.bar = 123 //You should use setState to set value like this: this.setState({foo: {bar: 123}}); }; render() { return <Child bar={this.state.foo.bar} /> } Child { render() { return <div>{this.props.bar}</div> } } }
Twój kod wygląda na nieprawidłowy. Nie mogę przetestować tego kodu.
źródło
<Child bar={this.state.foo.bar} />
?export default function DataTable({ col, row }) { const [datatable, setDatatable] = React.useState({}); useEffect(() => { setDatatable({ columns: col, rows: row, }); /// do any thing else }, [row]); return ( <MDBDataTableV5 hover entriesOptions={[5, 20, 25]} entries={5} pagesAmount={4} data={datatable} /> ); }
ten przykład służy
useEffect
do zmiany stanu poprops
zmianie.źródło
Użyj funkcji setState. Więc możesz to zrobić
this.setState({this.state.foo.bar:123})
wewnątrz metody zdarzenia handle.
Po zaktualizowaniu stanu wyzwoli zmiany i nastąpi ponowne renderowanie.
źródło
Prawdopodobnie powinieneś uczynić Child jako komponent funkcjonalny, jeśli nie zachowuje żadnego stanu i po prostu renderuje właściwości, a następnie wywołuje je z rodzica. Alternatywą jest użycie punktów zaczepienia z komponentem funkcjonalnym (useState), co spowoduje ponowne renderowanie komponentu bezstanowego.
Nie powinieneś także zmieniać propozycji, ponieważ są one niezmienne. Utrzymuj stan komponentu.
Child = ({bar}) => (bar);
źródło
Miałem ten sam problem. Miałem
Tooltip
komponent, który otrzymywałshowTooltip
propozycję, który aktualizowałem naParent
podstawie komponentu na podstawieif
warunku, był aktualizowany wParent
komponencie, aleTooltip
komponent nie był renderowany.const Parent = () => { let showTooltip = false; if(....){ showTooltip = true; } return( <Tooltip showTooltip={showTooltip}></Tooltip> ) }
Błąd, który popełniłem, to zadeklarowanie
showTooltip
jako let.Zrozumiałem, co robię źle, naruszyłem zasady renderowania. Zastąpienie go hookami spełniło swoje zadanie.
const [showTooltip, setShowTooltip] = React.useState<boolean>(false);
źródło
zdefiniuj zmienione właściwości w mapStateToProps metody connect w komponencie potomnym.
function mapStateToProps(state) { return { chanelList: state.messaging.chanelList, }; } export default connect(mapStateToProps)(ChannelItem);
W moim przypadku kanał channelList jest aktualizowany, więc dodałem chanelList w mapStateToProps
źródło