How can I run an action when a state changes?
You can't use didSet
observer on @State
but you can on an ObservableObject
property.
import SwiftUI
import Combine
final class SelectionStore: ObservableObject {
var selection: SectionType = .top {
didSet {
print("Selection changed to \(selection)")
}
}
// @Published var items = ["Jane Doe", "John Doe", "Bob"]
}
Then use it like this:
import SwiftUI
enum SectionType: String, CaseIterable {
case top = "Top"
case best = "Best"
}
struct ContentView : View {
@ObservedObject var store = SelectionStore()
var body: some View {
List {
Picker("Selection", selection: $store.selection) {
ForEach(FeedType.allCases, id: \.self) { type in
Text(type.rawValue).tag(type)
}
}.pickerStyle(SegmentedPickerStyle())
// ForEach(store.items) { item in
// Text(item)
// }
}
}
}
How to perform an action only when a state is changed?
The problem is that you're performing the check continuously, and for every check you execute the if
-statement in which you send the IR code. Consequently, your application will keep sending IR codes as fast as it can.
If you only want to send do something (send an IR code) on a state change, you should remember the state, and perform an action on a state change instead.
This is very easy to implement by adding a variable previous_connection_state
. Example code below (this would replace the loop()
from your current code).
esp_a2d_connection_state_t previous_connection_state;
void loop() {
esp_a2d_connection_state_t connection_state = a2dp_sink.get_connection_state();
if (connection_state != previous_connection_state) {
if (connection_state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
irsend.sendRaw(rawData, 71, 38);
}
if (connection_state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
irsend.sendRaw(rawData2, 71, 38);
}
previous_connection_state = connection_state;
}
}
Execute Function when a State Variable Changes inside of a useEffect() Hook
Store graph
in a React ref so it persists through rerenders. In hideN
use an Optional Chaining operator on graphRef.current
to call the findById
function.
Add hideNode
state as a dependency to the useEffect
hook and move the hideN
call out of the conditional block that is only instantiating a graph
value to store in the ref.
const graphRef = useRef(null);
const ref = useRef(null);
//Hide Node State
const [hideNode, sethideNode] = useState("");
const hideN = () => {
const node = graphRef.current?.findById(hideNode);
node.hide();
};
useEffect(() => {
if (!graphRef.current) {
graphRef.current = new G6.Graph(cfg);
graphRef.current.data(data);
graphRef.current.render();
}
hideN();
}, [hideNode]);
UseEffect, Re-run on state change?
This kind of code execution cannot be implicit stopped.
Answer:
The useEffect-callback will be called again, even if the previous is not done
You could use a debounce or blocking behavior and cancel/ignore the previous action.
UseEffect supports a clean-up method. You could return a function to cancel a timer with a given throttle value (for debounce).
As stated by the react docs
Why did we return a function from our effect? This is the optional cleanup mechanism for effects. Every effect may return a function that cleans up after it. This lets us keep the logic for adding and removing subscriptions close to each other. They’re part of the same effect!
When exactly does React clean up an effect? React performs the cleanup when the component unmounts. However, as we learned earlier, effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time. We’ll discuss why this helps avoid bugs and how to opt out of this behavior in case it creates performance issues later below.
Solution
Stackblitz Example
Is it possible to create a promise that get fulfilled by a state change in react-native?
Don't go polling. Instead, pass the resolve
function as an argument to openInteractionModal
, and call it together with setImportantState
from the modal dialog.
If that is for some reason not possible, you can use a ref to store the resolve
function and run it from an effect when the state changes:
const onImportantStateChange = useRef();
useEffect(() => {
if (!onImportantStateChange.current) return;
if (importantState === 'complete') {
onImportantStateChange.current('success');
onImportantStateChange.current = undefined;
} else if (importantState === 'failed') {
onImportantStateChange.current(Promise.reject(new Error('failure')));
onImportantStateChange.current = undefined;
}
}, [importantState])
const run = async () => {
return new Promise(resolve => {
onImportantStateChange.current = resolve;
// This function will open a modal
// where users will eventually change the important state
openInteractionModal();
});
}
Related Topics
How to Calculate Uilabel Width Based on Text Length
iOS Keeping Old Launch Screen and App Icon After Update
Iad Is Shutting Down. Should I Remove the Iad Framework from All My Applications
Where's the Difference Between Setobject:Forkey: and Setvalue:Forkey: in Nsmutabledictionary
Developing for iOS Device in Windows Environment with Flutter
Insert CSS into Loaded HTML in Uiwebview/Wkwebview
Rsa Implementations in Objective C
Detect First Launch of iOS App
How to Change Locale Programmatically with Swift
How to Get an Iso 8601 Date on iOS
How to Change Inside Background Color of Uisearchbar Component on iOS
Presenting a Uialertcontroller Properly on an iPad Using iOS 8
Connect Objective-C Framework to Swift iOS 8 App (Parse Framework)
How to Create Layout Constraints Programmatically
Comparing Nsdates Without Time Component
How to Make Uitextview Detect Links for Website, Mail and Phone Number