State
State represents data that can change over time. Unlike props, state is managed by the component itself and can be updated.
Initializing State
Initialize state in the constructor:
from pyreact import element, Component
class Counter(Component):
def __init__(self, props):
super().__init__(props)
self.state = {'count': 0}
Updating State
Use setState() to update state:
class Counter(Component):
def __init__(self, props):
super().__init__(props)
self.state = {'count': 0}
def increment(self, event):
# ✅ Correct: Use setState
self.setState({'count': self.state['count'] + 1})
def bad_increment(self, event):
# ❌ Wrong: Never modify state directly
self.state['count'] += 1 # Don't do this!
State Updates are Merged
setState() merges the new state with the existing state:
class Form(Component):
def __init__(self, props):
super().__init__(props)
self.state = {
'name': '',
'email': '',
'age': 0
}
def update_name(self, event):
# Only updates 'name', preserves 'email' and 'age'
self.setState({'name': event.target.value})
def update_email(self, event):
self.setState({'email': event.target.value})
Functional Updates
When new state depends on previous state, use a function:
class Counter(Component):
def __init__(self, props):
super().__init__(props)
self.state = {'count': 0}
def increment(self, event):
# Use function for derived state
self.setState(lambda state: {'count': state['count'] + 1})
def increment_three_times(self, event):
# Multiple updates
self.setState(lambda state: {'count': state['count'] + 1})
self.setState(lambda state: {'count': state['count'] + 1})
self.setState(lambda state: {'count': state['count'] + 1})
State is Local
State is local to the component:
class App(Component):
def render(self):
return element('div', {},
element(Counter, {}), # Has its own state
element(Counter, {}), # Has its own state
element(Counter, {}) # Has its own state
)
Lifting State Up
Share state between components by lifting it to their common ancestor:
class App(Component):
def __init__(self, props):
super().__init__(props)
self.state = {'temperature': 0}
def handle_change(self, temp):
self.setState({'temperature': temp})
def render(self):
return element('div', {},
element(TemperatureInput, {
'temperature': self.state['temperature'],
'onChange': self.handle_change
}),
element(BoilingVerdict, {
'celsius': self.state['temperature']
})
)
State vs Props
Props |
State |
|---|---|
Passed from parent |
Managed by component |
Read-only |
Can be updated |
Used for configuration |
Used for dynamic data |
External to component |
Internal to component |
Best Practices
Minimize state - Keep state as simple as possible
Lift state up - Share state by lifting to common ancestor
Don’t duplicate state - Compute derived values instead
Use setState - Never modify state directly
Next Steps
Events - Learn about event handling
Hooks API - Explore built-in hooks
Lifecycle Methods - Learn about lifecycle methods