The application uses apollo server and react Native in the frontend. In the backend I use apollo server. The request works via the Playground and I don't get any errors. Queries in the frontend without parameters also work perfectly. When I make a mutation in the frontend, I get the following error error: Response not successful: Received status code 400.
src/queries/queries.js
import { gql } from "#apollo/client";
export const SIGNUP_USERS = gql`
mutation createUser($newUser:UserInput!) {
CreateUser(newUser:$newUser){
firstName
}
}
src/components/Signup.js
import { useMutation } from '#apollo/client'
import { SIGNUP_USERS } from '../gqloperations/Mutation'
const Signup = () => {
const [formData,setFormData] = useState({firstName:'',LastName:'',email:'',password:''})
const [signupUser,{data,loading,error}] = useMutation(SIGNUP_USERS)
if(loading) return <Text>Loading... 🚀</Text>
if(error) return console.log("error is=====>",error)
const handleChange = (name,value) => {
setFormData({
...formData,
[name] : value
})
}
const handleSubmit = () => {
console.log("signup data is",formData)
signupUser({
variables:{
newUser:formData
}
})
}
return (
<View style={styles.container}>
<View style={styles.innerContainer}>
<View style={styles.innerView}>
<View style={styles.titleView} >
<Text style={styles.title}>Signup</Text>
</View>
{ error && <View> <Text style={{color:'red'}}>{error.message}</Text></View> }
{ data && data.user && <View><Text style={{color:'green'}}>{data.firstName} Signup sucessfully!</Text> </View> }
<View style={{height:hp('5%')}}></View>
<View style={styles.textInputView}>
<TextInput placeholder='Please Enter FirstName' style={styles.textInput} onChangeText={(text) => handleChange('firstName',text)} value={formData.firstName}
/>
</View>
<View style={styles.textInputView}>
<TextInput placeholder='Please Enter LastName' style={styles.textInput} onChangeText={(text) => handleChange('LastName',text)} value={formData.LastName} />
</View>
<View style={styles.textInputView}>
<TextInput placeholder='Please Enter Email' style={styles.textInput} onChangeText={(text) => handleChange('email',text)} value={formData.email} />
</View>
<View style={styles.textInputView}>
<TextInput secureTextEntry={true} placeholder='Please password' style={styles.textInput} onChangeText={(text) => handleChange('password',text)} value={formData.password}/>
</View>
<TouchableOpacity style={styles.buttonView} onPress={handleSubmit} >
<Text style={styles.btnText}>Signup</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
What is wrong in my code ?
A 400 error from a GraphQL server is almost always an invalid query or mutation.
Your mutation:
mutation createUser($newUser:UserInput!) {
CreateUser(newUser:$newUser){
firstName
}
}
looks fine. Odds are that formData does not have the same shape as UserInput
variables:{ newUser:formData }
Possible issues:
missing a required key
has an unexpected key
has an invalid value for a key
Attempt the mutation from the playground first to troubleshoot.
Related
I want to save the values from all input fields to getdata(), but I am getting undefined value
export default function Signupfor(props) {
// const phoneInput = useRef < PhoneInput > null;
const [text, setTextname] = useState();
function getdata() {
console.log('dsd');
console.log(text);
}
const {userInfo, log} = props?.route?.params;
console.log(log.name);
return (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
value={userInfo.user.name}
onChangeText={text => setTextname(text)}
/>
<TextInput
style={styles.forminput}
label="Email"
value={userInfo.user.email}
onChangeText={text => setTextemail(text)}
/>
<TextInput
style={styles.forminput}
label="Whatsapp Number"
keyboardType="numeric"
value={userInfo.user.number}
onChangeText={text => setTextnumber(text)}
// value={this.state.myNumber}
maxLength={10} //setting limit of input
/>
</View>
<View style={styles.buttonw}>
<Button color="#7743DB" title="Lets Go" onPress={() => getdata()} />
</View>
</View>
);
}
Here, name and email should not be able to be edited. I want to pass the value from value={userInfo.user.name} to the getdata()
you can use formik package for making form in react native
Installation
yarn add formik
Usage
import { Formik } from "formik";
export default function Signupfor(props) {
const { userInfo, log } = props?.route?.params;
console.log(log.name);
return (
<Formik
initialValues={{
name: userInfo.user.name,
email: userInfo.user.email,
number: userInfo.user.number,
}}
onSubmit={async (values, actions) => {
try {
console.log("name", values.name);
console.log("phone", values.number);
const params = {
full_name: values.name,
email: values.email,
phone_number: values.number,
};
} catch (error) {
let message = error.message;
console.log(message)
} finally {
actions.setSubmitting(false);
}
}}
>
{({
handleChange,
setFieldValue,
handleSubmit,
values,
errors,
touched,
isSubmitting,
}) => (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
value={values.name}
onChangeText={handleChange("name")}
/>
<TextInput
style={styles.forminput}
label="Email"
value={values.email}
onChangeText={handleChange("email")}
/>
<TextInput
style={styles.forminput}
label="Whatsapp Number"
keyboardType="numeric"
value={values.number}
onChangeText={handleChange("number")}
// value={this.state.myNumber}
maxLength={10} //setting limit of input
/>
</View>
<View style={styles.buttonw}>
<Button
color="#7743DB"
title="Lets Go"
onPress={() => handleSubmit()}
/>
</View>
</View>
)}
</Formik>
);
}
Your original method doesn't populate the state unless you edit the text input field, this is because your initialState doesn't have a value to start with. so firing getData() is reading empty state if the fields havent been changed.
onChangeText={text => setTextname(text)}
Only fire if you edit the textInput field.
Also I think you might be missing props, so first check if you are getting the correct data from props by logging it.
Once you have confirmed the props are available.
Set the initialState for name to userInfo.user.name
const { userInfo } = props?.route?.params;
const [name, setName] = useState(userInfo.user.name);
Then pass the state name to your TextInput and it should populate the value by reading from state.
return (
<>
<TextInput
placeholder="name"
value={name}
onChangeText={(text) => setName(text)}
/>
<Button title="Submit" onPress={() => getData()} />
</>
)
Make sure to create states for any additional values you wish to save.
const [name, setName] = useState(userInfo.user.name);
const [email, setEmail] = useState(userInfo.user.email);
You can use a library like https://react-hook-form.com to check an example with react native on video.
Or you can right it yourself, in the example below any time you need access to input values you can read it from text and number
const UselessTextInput = () => {
const [text, onChangeText] = useState("Useless Text");
const [number, onChangeNumber] = useState(null);
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={onChangeText}
value={text}
/>
<TextInput
style={styles.input}
onChangeText={onChangeNumber}
value={number}
placeholder="useless placeholder"
keyboardType="numeric"
/>
</SafeAreaView>
);
};
You can do something like this!!
export default function Signupfor(props) {
const {userInfo, log} = props?.route?.params;
const [name, setName] = useState(userInfo?.user?.name);
const [phone, setPhone] = useState(userInfo?.user?.number);
function getdata() {
console.log("name",name)
console.log("phone",phone)
}
return (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
// this value must be same with useState
value={name}
onChangeText={text => setName(text)}
/>
<TextInput
style={styles.forminput}
label="Mobile"
value={phone}
onChangeText={text => setPhone(text)}
/>
</View>
<View style={styles.buttonw}>
<Button color="#7743DB" title="Lets Go" onPress={() => getdata()} />
</View>
</View>
);
}
Same goes for email.
I'm running into the issue with my login screen where people autofill in their emails so it leaves a space at the end of the screen. I want to clear that when they move to add their password so was thinking of doing a onBlur that could probably use a .trim() or .replace() but how do I use that with my setEmail useState?
Screen blow:
const LoginScreen = ({ navigation }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const LogInUser = async() => {
if(email && password) {
try {
await auth.signInWithEmailAndPassword(email, password)
setEmail('')
setPassword('')
setError('')
navigation.replace('Home')
console.log('User Logged In = ');
} catch (err){
setError('Email or Password is wrong!');
console.log(err);
}
}
}
return (
<DismissKeyboard>
<View style={styles.screenStyle}>
<View style={{ ...StyleSheet.absoluteFill }}>
<Image source={require('../../assets/images/AccountBG.png')} style={{ flex: 1, height: null, width: null}} />
</View>
<StatusBar hidden={true} />
<View style={styles.loginBox}>
<Text style={[styles.whiteText, styles.headTextH1, styles.headingBufferBottom]}>Welcome</Text>
<Text style={styles.errorMessage}>{error}</Text>
<TextInput
style={styles.inputStyles}
placeholder="Email"
placeholderTextColor="#000"
value={email}
onChangeText={setEmail}
onBlur={cleanEmail}
/>
<TextInput
style={styles.inputStyles}
secureTextEntry
placeholder="Password"
placeholderTextColor="#000"
value={password}
onChangeText={setPassword}
/>
<OGButton title="Login" onPress={()=> LogInUser()} />
</View>
<View style={[styles.registerBox, styles.whiteText]}>
<Text style={styles.whiteText}>Don't have an account? | </Text>
<Text style={[styles.underlineText, styles.whiteText]} onPress={() => navigation.navigate('Register')} >Register Here</Text>
</View>
</View>
</DismissKeyboard>
);
}
You can trim the values and setEmail and whatever checks needed in onChangeText
onChangeText={(val) => {
// have other checks if needed here
setEmail(val.trim())
}
}
I'm developing an application for a school project, and in this application I have a camera component in each view. When I go back on a view the camera freeze.
There is my code of one view:
class LoginView extends React.Component {
constructor(props) {
super(props);
}
togglePseudo = pseudo => {
const action = {type: 'USER_PSEUDO', value: pseudo};
this.props.dispatch(action);
};
render() {
const {navigate} = this.props.navigation;
const userPseudo = this.props.userPseudo;
return (
<View style={style.mainContainer}>
<RNCamera
style={style.backgroundCamera}
type={RNCamera.Constants.Type.back}
flashMode={RNCamera.Constants.FlashMode.on}
androidCameraPermissionOptions={{
title: "Permission d'utiliser la camera",
message: "L'application necessite l'autorisation de la camera",
buttonPositive: 'Autoriser',
buttonNegative: 'Refuser',
}}
/>
<View style={style.goContainer}>
<TouchableOpacity
style={style.backButton}
onPress={() => navigate('HomeView')}>
<Image source={require('assets/images/back-button.png')} />
</TouchableOpacity>
<View style={style.centeredElements}>
<Text style={style.titleMission}>Mission "Pc"</Text>
<View style={style.modalChoosePseudo}>
<Text style={style.modaltitle}>Choisir un pseudo</Text>
<TextInput
style={style.pseudoInput}
onChangeText={pseudo => this.togglePseudo(pseudo)}
value={userPseudo}
/>
{userPseudo !== '' ? (
<TouchableOpacity
style={style.validateButton}
onPress={() => navigate('InGame')}>
<Text style={style.buttonText}>Valider</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={[style.validateButton, style.validateButtonDisabled]}
onPress={() =>
Alert.alert('Alerte', 'Veuillez entrer un pseudo')
}>
<Text
style={[style.buttonText, style.validateButtonDisabled]}>
Valider
</Text>
</TouchableOpacity>
)}
</View>
<Image
style={style.logoDimagine}
source={require('assets/images/logo_title_vertical.png')}
/>
</View>
</View>
</View>
);
}
}
I have already looked for solutions, so I tried what I found.
I've try to use componentDidMount with willFocus and willBlur, but it never detect them :
componentDidMount() {
const {navigation} = this.props;
navigation.addListener('willFocus', () =>
this.setState({focusedScreen: true}),
);
navigation.addListener('willBlur', () =>
this.setState({focusedScreen: false}),
);
}
I'm new to react native and so I'm wondering why I'm receiving an error like
"undefined is not an object (evaluating 'props.navigation.toggleDrawer')" when I try to click on hamburger menu in my Home
Here below my Home.js
const NavigatorHome = props => {
return (
<View>
<AppHeader navigation={props.navigation} title="Home" />
</View>
);
};
export default class Home extends Component {
state = {
users: []
}
async componentDidMount() {
const users = await ajax.fetchUsers();
//ET20200226 This was a warning
this.setState({users});
}
render() {
return (
<View>
<NavigatorHome></NavigatorHome>
<View>
<Text style={styles.h2text}>
List of requests
</Text>
<FlatList
data={this.state.users}
showsVerticalScrollIndicator={false}
renderItem={({item}) =>
<View style={styles.flatview}>
<Text style={styles.uuid}>{item.uuid}</Text>
</View>
}
keyExtractor={item => item.uuid}
/>
</View>
</View>
);
}
}
Here my AppHeader.js
const AppHeader = props => {
return (
<Header
//leftComponent={<HamburgerMenu navigation={props.navigation} />}
leftComponent={<Icon
color="#fff"
name="menu"
onPress={() => props.navigation.toggleDrawer()}
/>}
centerComponent={{
text: props.title,
style: { color: "#fff", fontWeight: "bold" }
}}
statusBarProps={{ barStyle: "light-content" }}
/>
);
};
export default AppHeader;
Can someone help me to figure out how to fix it?
The reason for the error is that props.navigation is undefined in NavigatorHome. you must pass props.navigation to NavigatorHome. Your code should be as follows:
<View>
<NavigatorHome navigation={this.props.navigation}></NavigatorHome>
<View>
I wanted to show a list of data fetched from API inside DropdownModal (https://github.com/sohobloo/react-native-modal-dropdown) . The data is user address consists of name , state , country and all related to address . But it won't show inside the dropdown and it shows loading icon which means it is null or undefined . But i did have the data fetched from the API which i verify by making alert to error and result ( yup both giving the same data which is the address ) .
Below are my code .
const {getAddresses} = auth;
var {width, height} = Dimensions.get('window');
class RegisterEventOne extends React.Component {
constructor(props) {
super(props);
this.state = {
event_id: '',
tshirt_size: '',
size: '',
address: '',
addressx: '',
};
this.onResult = this.onResult.bind(this);
this.onError = this.onError.bind(this);
}
handleWithDropdownCategory = id => {
this.setState({event_id: id});
};
handleWithDropdownSize = size => {
this.setState({tshirt_size: size});
};
TShirtSize = size => {
this.setState({size: size});
};
setAddress = address => {
this.setState({addressx: address})
}
componentDidMount() {
this.props.getAddresses(this.props.event.id, this.onResult, this.onError);
}
onError(error) {
alert(JSON.stringify(error));
}
onResult(result) {
this.setState({
address: result,
});
}
render() {
return (
<React.Fragment>
<StatusBar backgroundColor="black" barStyle="light-content" />
<SafeAreaView style={styles.container}>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={styles.scrollView}>
<View>
<Text style={styles.eventname}>{this.props.event.name}</Text>
<ModalDropdown
dropdownStyle={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
style={styles.dropdown}
onSelect={(index, value) => {
this.handleWithDropdownCategory(value);
}}
options={this.props.event.categories.map(function(event) {
return event.name;
})}>
<View style={styles.dropdowncontainer}>
<Text>{this.state.event_id === '' ? 'Select Category' : this.state.event_id}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
<ModalDropdown
dropdownStyle={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
style={styles.dropdown}
onSelect={(index, value) => {
this.handleWithDropdownSize(value);
this.TShirtSize(index+1);
}}
options={this.props.event.tshirts.map(function(event, index) {
return event.size;
})}
>
<View style={styles.dropdowncontainer}>
<Text>{this.state.tshirt_size === '' ? 'Select Tshirt Size' : this.state.tshirt_size}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
<ModalDropdown
dropdownStyle={styles.dropdown}
style={styles.dropdown}
dropdownTextStyle={{fontSize:15}}
onSelect={(index, value) => {
this.setAddress(value);
}}
options={this.state.address !== '' ? this.state.address.map(function(address, index) {
return address.id;
}):null}
>
<View style={styles.dropdowncontainer}>
<Text>{this.state.addressx === '' ? 'Select Address' : this.state.addressx}</Text>
<Ionicons name="ios-arrow-down" size={20} color="black" />
</View>
</ModalDropdown>
{/* <Text style={styles.header}>Compete with ohters (Optional)</Text>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Set Date & Time (Time zone)"
/> */}
{/* <View style={styles.checkboxcontainer}>
<BouncyCheckbox
textColor="#000"
fillColor="orange"
fontFamily="JosefinSans-Regular"
text="Individual Competition"
/>
<BouncyCheckbox
textColor="#000"
fillColor="orange"
fontFamily="JosefinSans-Regular"
text="Team Competition"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Team member limit"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
<TextInput
style={styles.header}
onChangeText={text => onChangeText(text)}
placeholder="Username / Email"
/>
</View> */}
</View>
</ScrollView>
<View style={styles.processIndicator}>
<TouchableOpacity disabled>
<Text style={styles.textProcessPrimary}>Previous</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()=>Actions.RegisterEventThree({event_id: this.props.event.categories[0].event_id, category_id: this.state.event_id, size: this.state.size, address: this.state.addressx})}>
<Text style={styles.textProcessPrimary}>Next</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
</React.Fragment>
);
}
}
export default connect(
null,
{getAddresses},
)(RegisterEventOne);
The API :
export function getAddresses(data, callback) {
AsyncStorage.getItem('token').then(value => {
const token = JSON.parse(value);
fetch('https:apiurl.com', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'bearer' + token.access_token,
},
})
.then(response => response.json())
.then(response => callback(response.data))
.catch(error => callback(false, null, error.json()));
The loading indicator shows only if data(options) is undefined or null. Which means that you have no data at all, or data structure is bad.
You'v said that error alert is also triggered, which is not really a great thing. I don't know why the error is showing you some data tho. (except of error data).
Options should be passed in this format: ['data1', 'data2'].
Also, your taking the data from redux => this.props.event.categories instead of state. If you want to use redux, then you are missing some kind of mapStateToProps in connect fnc.
There is a lot of wrong patterns in this code. take a look at some examples of how to use redux and also take a look at examples in react-native-modal-dropdown github repo if you want to use that.
It's solved now .
I just added ,true,null behind response.data .
It would look like this :
.then(response => callback(response.data,true,null)