As someone who is knew to redux like state management, this is almost a complete deal breaker. You have the following defined as an action:
struct StandardAction: Action {
// identifies the action
let type: String
// provides information that is relevant to processing this action
// e.g. details about which post should be favorited
let payload: [String : AnyObject]?
// this flag is used for serialization when working with ReSwift Recorder
let isTypedAction: Bool
}
Neat! So I want to take a string, send a payload that I will set as the new string. So I would set it in the action, and then in the payload I would....
func authenticationReducer(state: AuthenticationState?, action: Action) -> AuthenticationState {
var state = state ?? initialAuthenticationState()
switch action {
case _ as ReSwiftInit:
break
case let action as SetOAuthURL:
state.oAuthURL = action.oAuthUrl
case let action as UpdateLoggedInState:
state.loggedInState = action.loggedInState
default:
break
}
return state
}
wtf is this? Is action.oAuthUrl the payload? Is there even a payload even here? Who knows! Syntax is inconsistent throughout (every section is a different example from scratch hurray!) and variables are not the same. Complete dumpster fire.
I suggest you take a look at https://github.com/ReSwift/ReSwift/blob/8fb16bca793850f002fe1b43926e37370aad65e1/Docs/Getting%20Started%20Guide.md#minimal-working-example which is in that guide and provides a minimal working example of all the parts of ReSwift.
The example you've copied here shows a reducer that handles a few different action types such as SetOAuthURL, which would be defined as follows:
struct SetOAuthURL: Action {
let oAuthUrl: URL
}
StandardAction is the action type to be used if you need to support recording / rewinding of actions via https://github.com/ReSwift/ReSwift-Recorder
Good point that every example is different, @patientplatypus. Never thought about that. Now that you _do_ come from a Redux background, can you help me sort this out and explain what you expect?
Ok. Sorry, for the static. I'm under a lot of stress lately (still no excuse).
You should update the docs with this example rather than the "counter" one. That example is not a fully functional battlestation because 1) it doesn't pass payloads which is what most people starting out want and 2) it doesn't explain this for retarded giraffes.
Step 1. _Install using cocoa pods_
Install using cocoa pods or one of the other installation methods already mentioned.
Step 2. _Modify AppDelegate.swift file to reference what will go in the State.swift file (which you will make)_
Add these lines at the top before @UIApplicationMain tag and after import UIKit
import ReSwift
let mainStore = Store<AppState>(
reducer: mainReducer,
state: nil
)
Step 3. _You now need to make a new file State.swift that you just referenced_
import Foundation
import ReSwift
struct AppState: StateType {
var MyName: String = ""
}
Step 4. _Inside your ViewController.swift file send the action to ReSwift dispatch._
Select a ViewController that references a storyboard in your ViewController.swift file where you will be using to make this example work. Make sure that the storyboard class in your main.storyboard matches the class of your ViewController class that you will be referencing in your ViewController.swift file. You can set this by clicking on the yellow circle at the top left of the storyboard gui in main.storyboard and in interface builder going to the identity inspector tab and naming the custom class.
Make a button by control dragging from your storyboard and selecting action. Name this button MyButtonThatSetsName. Set a payload that you want to send (here I have set "platypus"). You can later call a text variable from elsewhere in your component, but for now keep this trivial.
@IBAction func MyButtonThatSetsName(_ sender: UITextField) {
mainStore.dispatch(MyNameAction(payload: "platypus"));
}
Step 5. _Since we are dispatching this action we now need to make the actions.swift file where this will be dispatched to_
Make a new file named Actions.swift.
Inside the file put the following.
import ReSwift
struct MyNameAction: Action {
let payload: String
}
Step 6. _Now that we have made the actions, we need to make a reducer file and set the new state._
Make a new file named Reducers.Swift
Put the following inside it.
import ReSwift
func mainReducer(action: Action, state: AppState?) -> AppState {
var state = state ?? AppState()
switch action {
case let action as MyNameAction:
state.MyName = action.payload
default:
break
}
return state
}
Step 7. _Now, if everything was done correctly, you should be able to output the result in our ViewController.swift file_
Add the StoreSubscriber dependency to your ViewController so it looks like this:
class ViewController1: UIViewController, **StoreSubscriber** {
Add lifecycle hooks within the view controller so that the controller will subscribe and unsubscribe on load.
override func viewWillAppear(_ animated: Bool) {
mainStore.subscribe(self)
}
override func viewWillDisappear(_ animated: Bool) {
mainStore.unsubscribe(self)
}
Add the label that you want your name to populate on your storyboard and set an outlet like so:
@IBOutlet weak var MyNameLabel: UILabel!
Finally set your new state function so that the label is updated when you push the button and the state is updated within reswift.
func newState(state: AppState) {
self.MyNameLabel.text = "\(mainStore.state.MyName)"
}
Step 8. _Yay we're done! Now what? Next Steps._
If everything was done correctly, you should see that your new label will populate with the hardcoded name you have entered at the beginning. Now, if you would like, you can as a next step take user input from a text field to populate the username. A step after that is to have information populate the name field in one storyboard/viewcontroller and have it retrieved in another. Remember one of the great things about uni-directional data flow is that you don't have to push state between view controllers, you can push and retrieve from state. Happy hunting.
So.....that's the kind of thing, that would have saved me a few hours of frustration. I don't know if everything in here is 100% correct, but it might be useful for the little people (i.e. me).
EDIT: edited to include the store subscriber and life cycle hooks in step 7.
Amazing effort, @patientplatypus! Thanks!
@patientplatypus I was just reading the example again to plan a documentation change. What struck me is the term "payload" for the text property. In your initial comment, it seemed you recognize this term put meaning into it -- yet you picked this instead of a more favorable, because less generic, property like name. I don't intend to point at you and tell you your code is bad or anything. Instead, I'd like to ask you to define or describe what "payload" means (or meant) to you. The Redux.js docs simply use it as part of the definition for Action. I'd like to help Redux-savvy people map known concepts to ReSwift, and this might be helpful and I'm aware that I could be missing something important.
Since #270, StandardAction is not a part of the core ReSwift anymore. So at least parts of the initial source of confusion is gone, by the way :)
Most helpful comment
Ok. Sorry, for the static. I'm under a lot of stress lately (still no excuse).
You should update the docs with this example rather than the "counter" one. That example is not a fully functional battlestation because 1) it doesn't pass payloads which is what most people starting out want and 2) it doesn't explain this for retarded giraffes.
Here is the example that is the most trivial for n00bs.
Step 1. _Install using cocoa pods_
Install using cocoa pods or one of the other installation methods already mentioned.
Step 2. _Modify AppDelegate.swift file to reference what will go in the State.swift file (which you will make)_
Add these lines at the top before
@UIApplicationMaintag and afterimport UIKitStep 3. _You now need to make a new file State.swift that you just referenced_
Step 4. _Inside your ViewController.swift file send the action to ReSwift dispatch._
Select a ViewController that references a storyboard in your ViewController.swift file where you will be using to make this example work. Make sure that the storyboard class in your main.storyboard matches the class of your ViewController class that you will be referencing in your ViewController.swift file. You can set this by clicking on the yellow circle at the top left of the storyboard gui in main.storyboard and in interface builder going to the identity inspector tab and naming the custom class.
Make a button by control dragging from your storyboard and selecting action. Name this button
MyButtonThatSetsName. Set a payload that you want to send (here I have set "platypus"). You can later call a text variable from elsewhere in your component, but for now keep this trivial.Step 5. _Since we are dispatching this action we now need to make the actions.swift file where this will be dispatched to_
Make a new file named Actions.swift.
Inside the file put the following.
Step 6. _Now that we have made the actions, we need to make a reducer file and set the new state._
Make a new file named Reducers.Swift
Put the following inside it.
Step 7. _Now, if everything was done correctly, you should be able to output the result in our ViewController.swift file_
Add the StoreSubscriber dependency to your ViewController so it looks like this:
class ViewController1: UIViewController, **StoreSubscriber** {Add lifecycle hooks within the view controller so that the controller will subscribe and unsubscribe on load.
Add the label that you want your name to populate on your storyboard and set an outlet like so:
@IBOutlet weak var MyNameLabel: UILabel!Finally set your new state function so that the label is updated when you push the button and the state is updated within reswift.
Step 8. _Yay we're done! Now what? Next Steps._
If everything was done correctly, you should see that your new label will populate with the hardcoded name you have entered at the beginning. Now, if you would like, you can as a next step take user input from a text field to populate the username. A step after that is to have information populate the name field in one storyboard/viewcontroller and have it retrieved in another. Remember one of the great things about uni-directional data flow is that you don't have to push state between view controllers, you can push and retrieve from state. Happy hunting.
So.....that's the kind of thing, that would have saved me a few hours of frustration. I don't know if everything in here is 100% correct, but it might be useful for the little people (i.e. me).
EDIT: edited to include the store subscriber and life cycle hooks in step 7.