我刚刚使用infinitered/ignite开始了一个新项目。
我已将getUserToken
功能添加到APITestScreen
所以我知道该函数按预期工作,但我无法将方法与onPress
函数挂钩到按钮I added to the LaunchScreen。
我已将其导入视图,但单击按钮时没有任何反应。我添加了一个警报和一个console.log,但它们没有被触发。单击按钮后,如何才能运行 fetchUserToken ?
整个项目发布了posted at Github。
我的观点
import getUserToken from '../Sagas/AuthSagas.js';
<RoundedButton text="Fetch token" onPress={ getUserToken } />
应用/终极版/ AuthRedux.js
import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'
/* ------------- Types and Action Creators ------------- */
const { Types, Creators } = createActions({
tokenRequest: ['username'],
tokenSuccess: ['token'],
tokenFailure: null
})
export const AuthTypes = Types
export default Creators
/* ------------- Initial State ------------- */
export const INITIAL_STATE = Immutable({
token: null,
fetching: null,
error: null,
username: null
})
/* ------------- Reducers ------------- */
// request the token for a user
export const request = (state, { username }) =>
state.merge({ fetching: true, username, token: null })
// successful token lookup
export const success = (state, action) => {
const { token } = action
return state.merge({ fetching: false, error: null, token })
}
// failed to get the token
export const failure = (state) =>
state.merge({ fetching: false, error: true, token: null })
/* ------------- Hookup Reducers To Types ------------- */
export const reducer = createReducer(INITIAL_STATE, {
[Types.TOKEN_REQUEST]: request,
[Types.TOKEN_SUCCESS]: success,
[Types.TOKEN_FAILURE]: failure
})
应用/萨加斯/ AuthSagas.js
import { call, put } from 'redux-saga/effects'
import { path } from 'ramda'
import AuthActions from '../Redux/AuthRedux'
export function * getUserToken (api, action) {
console.tron.log('Hello, from getUserToken');
alert('in getUserToken');
const { username } = action
// make the call to the api
const response = yield call(api.getUser, username)
if (response.ok) {
const firstUser = path(['data', 'items'], response)[0]
const avatar = firstUser.avatar_url
// do data conversion here if needed
yield put(AuthActions.userSuccess(avatar))
} else {
yield put(AuthActions.userFailure())
}
}
萨加斯/ index.js
export default function * root () {
yield all([
// some sagas only receive an action
takeLatest(StartupTypes.STARTUP, startup),
// some sagas receive extra parameters in addition to an action
takeLatest(GithubTypes.USER_REQUEST, getUserAvatar, api),
// Auth sagas
takeLatest(AuthTypes.TOKEN_REQUEST, getUserToken, api)
])
}
答案 0 :(得分:4)
Sagas很棒,因为它们允许长时间运行的进程以完全解耦的方式控制应用程序流,并且可以通过操作排序,允许您并行/取消/分叉/协调sagas以在集中的位置编排应用程序逻辑(即将其视为能够将行动联系在一起,并在此过程中加入副作用)
通过导入您的生成器功能并直接调用它,就像普通功能一样无法正常工作,如果它确实绕过了传奇功能,例如,如果您再按第二次或第三次按下该按钮,它将始终从头到尾再次执行整个生成器,因为它们涉及异步操作可能会导致您尝试存储或使用令牌,然后该令牌会立即被后续传奇失效
更好的做法是让你的传奇总是倾听特定的行动,以触发更多的工人传奇,保持他们解耦,并允许他们控制自己的流量。
在这种情况下,你会发送一个动作onPress
,并有一个长期运行的父传奇,听取该动作,然后交给你当前的一个来做实际的工作。这个监听传奇然后可以控制使用takeLatest
取消之前的调用取消之前的传奇调用,这样当前一个按钮按下而前一个仍然在飞行时总是优先,并且你的令牌不会意外地变得陈旧
// AuthActions.js
// add a new action (or more probably adapt fetchUserToken to suit)...
export const GET_USER_TOKEN = 'auth/get-user-token'
export const getUserToken = (username) => ({
type: GET_USER_TOKEN,
payload: username
})
//查看
import {getUserToken} from './AuthActions'
// this now dispatches action (assumes username is captured elsewhere)
// also assumes store.dispatch but that would more likely be done via `connect` elsewhere
<RoundedButton text="Fetch token" onPress={ () => store.dispatch(getUserToken(this.username)) } />
// AuthSagas.js
import api from 'someapi'
import actions from 'someactions'
import {path} from 'ramda'
import {put, call, takeLatest} from 'redux-saga/effects'
import AuthActions from '../Redux/AuthRedux'
// this will be our long running saga
export function* watchRequestUserToken() {
// listens for the latest `GET_USER_TOKEN` action,
// `takeLatest` cancels any currently executing `getUserToken` so that is always up to date
yield takeLatest(AuthActions.GET_USER_TOKEN, getUserToken)
}
// child generator is orchestrated by the parent saga
// no need to export (unless for tests) as it should not be called by anything outside of the sagas
function* getUserToken (action) { // the actual action is passed in as arg
const username = action.payload
// make the call to the api
const response = yield call(api.getUser, username)
if (response.ok) {
const firstUser = path(['data', 'items'], response)[0]
const avatar = firstUser.avatar_url
// do data conversion here if needed
yield put(AuthActions.userSuccess(avatar))
} else {
yield put(AuthActions.userFailure())
}
}
// main.js(取自https://redux-saga.js.org/的示例)适用于套件
import { createStore, applyMiddleware } from 'redux'
import createSagaMiddleware from 'redux-saga'
import {reducer} from './AuthRedux'
import {watchRequestUserToken} from './AuthSagas'
// create the saga middleware
const sagaMiddleware = createSagaMiddleware()
// mount it on the Store
export const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
)
// then run the saga
sagaMiddleware.run(watchRequestUserToken)
答案 1 :(得分:0)
在按钮上,您正在调用fetchUserTocken
,但在脚本中您可以定义getUserToken
。