gpt4 book ai didi

javascript - 使用 API react Native Redux Ignite 错误 "uncaught at check"

转载 作者:行者123 更新时间:2023-11-29 23:25:19 24 4
gpt4 key购买 nike

你好,我还是 react native 的新手,我很困惑如何使用 react redux,尤其是对于 ignite 模板。我遵循本教程 https://medium.com/skyshidigital/interaksi-api-dengan-ignite-react-native-f83bf35a23f5 .这是我最新的错误“检查时未捕获”,“take(patternOrChannel): patternOrChannel is undefined”。请帮助告诉我我的代码哪里出错了。

API.js:

// a library to wrap and simplify api calls
import apisauce from 'apisauce'

// our "constructor"
const create = (baseURL = 'http://localhost:4200/') => {
// ------
// STEP 1
// ------
//
// Create and configure an apisauce-based api object.
//
const api = apisauce.create({
// base URL is read from the "constructor"
baseURL,
// here are some default headers
headers: {
'Cache-Control': 'no-cache'
},
// 10 second timeout...
timeout: 10000
})

// ------
// STEP 2
// ------
//
// Define some functions that call the api. The goal is to provide
// a thin wrapper of the api layer providing nicer feeling functions
// rather than "get", "post" and friends.
//
// I generally don't like wrapping the output at this level because
// sometimes specific actions need to be take on `403` or `401`, etc.
//
// Since we can't hide from that, we embrace it by getting out of the
// way at this level.
//
const getRoot = () => api.get('')
const getRate = () => api.get('rate_limit')
const getUser = (username) => api.get('search/users', {q: username})
const getUsers = () => api.get('/users')
// ------
// STEP 3
// ------
//
// Return back a collection of functions that we would consider our
// interface. Most of the time it'll be just the list of all the
// methods in step 2.
//
// Notice we're not returning back the `api` created in step 1? That's
// because it is scoped privately. This is one way to create truly
// private scoped goodies in JavaScript.
//
return {
// a list of the API functions from step 2
getRoot,
getRate,
getUser,
getUsers
}
}

// let's return back our create method as the default.
export default {
create
}

UsersRedux.js

import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'

/* ------------- Types and Action Creators ------------- */

const { Types, Creators } = createActions({
usersRequest: null,
usersSuccess: ['data'],
usersFailure: null
})

export const UsersTypes = Types
export default Creators

/* ------------- Initial State ------------- */

export const INITIAL_STATE = Immutable({
data: null,
fetching: null,
payload: null,
error: null
})

/* ------------- Reducers ------------- */

// request the data from an api
export const request = (state, { data }) =>
state.merge({ fetching: true, payload: null })

// successful api lookup
export const success = (state, action) => {
const { payload } = action
return state.merge({ fetching: false, error: null, data })
}

// Something went wrong somewhere.
export const failure = state =>
state.merge({ fetching: false, error })

/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer(INITIAL_STATE, {
[Types.USERS_REQUEST]: request,
[Types.USERS_SUCCESS]: success,
[Types.USERS_FAILURE]: failure
})

来自 Redux 文件夹的 index.js:

import { combineReducers } from 'redux'
import configureStore from './CreateStore'
import rootSaga from '../Sagas/'

export default () => {
/* ------------- Assemble The Reducers ------------- */
const rootReducer = combineReducers({
nav: require('./NavigationRedux').reducer,
github: require('./GithubRedux').reducer,
login: require('./LoginRedux').reducer,
search: require('./SearchRedux').reducer,
users: require('./UsersRedux').reducer
})

return configureStore(rootReducer, rootSaga)
}

UsersSagas.js:

/* ***********************************************************
* A short word on how to use this automagically generated file.
* We're often asked in the ignite gitter channel how to connect
* to a to a third party api, so we thought we'd demonstrate - but
* you should know you can use sagas for other flow control too.
*
* Other points:
* - You'll need to add this saga to sagas/index.js
* - This template uses the api declared in sagas/index.js, so
* you'll need to define a constant in that file.
*************************************************************/

import { call, put } from 'redux-saga/effects'
import UsersActions from '../Redux/UsersRedux'

export function * getUsers (api, action) {
const { data } = action
// make the call to the api
const response = yield call(api.getUsers, data)

// success?
if (response.ok) {
// You might need to change the response here - do this with a 'transform',
// located in ../Transforms/. Otherwise, just pass the data back from the api.
yield put(UsersActions.usersSuccess(response.data))
} else {
yield put(UsersActions.usersFailure())
}
}

来自 Sagas 的 index.js

import { takeLatest, all } from 'redux-saga/effects'
import API from '../Services/Api'
import FixtureAPI from '../Services/FixtureApi'
import DebugConfig from '../Config/DebugConfig'

/* ------------- Types ------------- */

import { StartupTypes } from '../Redux/StartupRedux'
import { GithubTypes } from '../Redux/GithubRedux'
import { LoginTypes } from '../Redux/LoginRedux'
import { UsersTypes } from "../Redux/UsersRedux";

/* ------------- Sagas ------------- */

import { startup } from './StartupSagas'
import { login } from './LoginSagas'
import { getUserAvatar } from './GithubSagas'
import { getUsers } from "./UsersSagas"

/* ------------- API ------------- */

// The API we use is only used from Sagas, so we create it here and pass along
// to the sagas which need it.
const api = DebugConfig.useFixtures ? FixtureAPI : API.create()

/* ------------- Connect Types To Sagas ------------- */

export default function * root () {
yield all([
// some sagas only receive an action
takeLatest(StartupTypes.STARTUP, startup),
takeLatest(LoginTypes.LOGIN_REQUEST, login),

// some sagas receive extra parameters in addition to an action
takeLatest(GithubTypes.USER_REQUEST, getUserAvatar, api),
takeLatest(UsersTypes.USER_REQUEST, getUsers, api)
])
}

登录屏幕.js:

import React, { PropTypes } from "react";
import { View, ScrollView, Text, TextInput, TouchableOpacity, Image, Keyboard, LayoutAnimation } from "react-native";
import { connect } from "react-redux";
import Styles from "./Styles/LoginScreenStyles";
import { Images, Metrics } from "../Themes";
import LoginActions from "../Redux/LoginRedux";
import { Button, Text as NBText, Contant, Form, Item, Input, Label, StyleProvider } from "native-base";
import buttonTheme from '../../native-base-theme/components/';
import commonColor from '../../native-base-theme/variables/commonColor';
import UsersActions from "../Redux/UsersRedux";

class LoginScreen extends React.Component {
static propTypes = {
dispatch: PropTypes.func,
fetching: PropTypes.bool,
attemptLogin: PropTypes.func,
getUsers: PropTypes.func
};

isAttempting = false;
keyboardDidShowListener = {};
keyboardDidHideListener = {};

constructor(props) {
super(props);
this.props.getUsers();
this.state = {
username: "",
password: "",
visibleHeight: Metrics.screenHeight,
topLogo: { width: Metrics.screenWidth - 40 },
};
this.isAttempting = false;
}

componentWillReceiveProps(newProps) {
this.forceUpdate();
// Did the login attempt complete?
if (this.isAttempting && !newProps.fetching) {
this.props.navigation.goBack();
}
}

componentWillMount() {
// Using keyboardWillShow/Hide looks 1,000 times better, but doesn't work on Android
// TODO: Revisit this if Android begins to support - https://github.com/facebook/react-native/issues/3468
this.keyboardDidShowListener = Keyboard.addListener("keyboardDidShow", this.keyboardDidShow);
this.keyboardDidHideListener = Keyboard.addListener("keyboardDidHide", this.keyboardDidHide);
}

componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}

keyboardDidShow = e => {
// Animation types easeInEaseOut/linear/spring
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
let newSize = Metrics.screenHeight - e.endCoordinates.height;
this.setState({
visibleHeight: newSize,
topLogo: { width: 100, height: 70 },
});
};

keyboardDidHide = e => {
// Animation types easeInEaseOut/linear/spring
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({
visibleHeight: Metrics.screenHeight - 100,
topLogo: { width: Metrics.screenWidth - 40 },
});
};

handlePressLogin = () => {
// const { username, password } = this.state
// this.isAttempting = true
// attempt a login - a saga is listening to pick it up from here.
// this.props.attemptLogin(username, password);
this.props.navigation.navigate("LaunchScreen");
};

handlePressRegister = () => {
// const { username, password } = this.state
// this.isAttempting = true
// attempt a login - a saga is listening to pick it up from here.
// this.props.attemptLogin(username, password);
this.props.navigation.navigate("RegisterScreen");
};

handleChangeUsername = text => {
this.setState({ username: text });
};

handleChangePassword = text => {
this.setState({ password: text });
};

render() {
const { username, password } = this.state;
const { fetching } = this.props;
const editable = !fetching;
const textInputStyle = editable ? Styles.textInput : Styles.textInputReadonly;
return (
<ScrollView
contentContainerStyle={{ justifyContent: "center" }}
style={[Styles.container, { height: this.state.visibleHeight }]}
keyboardShouldPersistTaps="always"
>
<Image source={require("../Images/tuku_omah_logo_login.jpeg")} style={[Styles.topLogo, this.state.topLogo]} />
<View style={Styles.form}>
<Form>
<Item stackedLabel>
<Label>Username</Label>
<Input
ref="username"
value={username}
editable={editable}
keyboardType="default"
returnKeyType="next"
autoCapitalize="none"
autoCorrect={false}
onChangeText={this.handleChangeUsername}
underlineColorAndroid="transparent"
onSubmitEditing={() => this.password._root.focus()}
/>
</Item>
<Item stackedLabel>
<Label>Password</Label>
<Input
ref={ref => (this.password = ref)}
value={password}
editable={editable}
keyboardType="default"
returnKeyType="go"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry
onChangeText={this.handleChangePassword}
underlineColorAndroid="transparent"
onSubmitEditing={this.handlePressLogin}
/>
</Item>
</Form>
<View style={[Styles.loginRow]}>
<StyleProvider style={buttonTheme(commonColor)}>
<Button style={{ flex: 1, justifyContent: "center" }} full onPress={this.handlePressLogin}>
<NBText>Sign In</NBText>
</Button>
</StyleProvider>
</View>
<Text style={Styles.registerText} onPress={this.handlePressRegister}>
Tidak punya akun? Daftar di sini
</Text>
</View>
</ScrollView>
);
}
}

const mapStateToProps = state => {
return {
//fetching: state.login.fetching,
users: state.users
};
};

const mapDispatchToProps = dispatch => {
return {
//attemptLogin: (username, password) => dispatch(LoginActions.loginRequest(username, password)),
getUsers: () => dispatch(UsersActions => dispatch(UsersActions.getUsers()))
};
};

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);

最佳答案

在您的 usersRedux.js 中定义您的用户类型。

其中之一是 UsersTypes.USERS_REQUEST。

在 sagas 的 index.js 中,您尝试在 UsersTypes.USER_REQUEST 上运行您的用户 saga。

此操作类型值不存在,您在 USERS_REQUEST 中缺少 S。

在这种情况下,您传递给 takeLatest 以开始您的传奇的 actionType 被称为模式。

关于javascript - 使用 API react Native Redux Ignite 错误 "uncaught at check",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49524159/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com