Handle null username in React Native - reactjs

I have a review section in my app which uses the user's username as the heading along with their review. Everything works well unless the user does not have a username set up yet. I am trying to create a condition where if the user does not have a username set, it will be Anonymous.
I am using Redux to add the reviews.
Here is my code where I dispatch my action along with the username, uid, and review to the action creator:
const review = this.props.review.review;
//const username = this.props.userData.username.username;
const uid = this.props.string.uid;
const username = () => {
if (!this.props.userData.username.username) {
return 'Anonymous';
}
return this.props.userData.username.username;
};
//dispatch action with my values
this.props.submitUserReview({ review, username, uid });
I appreciate any help and guidance with this issue. Cheers!
SOLVED:
I solved this by using lodash thanks to Noah Allen:
const username = _.get(userData, 'username.username', 'Anonymous')

Edit: Lodash one-liner:
const username = _.get(userData, 'username.username', 'Anonymous')
To fix your example, you really only need to add a pair of parenthesis (explanation below):
this.props.submitUserReview({ review, username: username(), uid });
Taking it a step further you should do this to help improve code readability, re-use, and abstraction:
function checkUsername (userData) {
// Checks for undefined, null, and a string with no characters:
if (userData && userData.username && userData.username.username && username.length > 0) {
return userData.username.username
}
// Default case:
return 'Anonymous'
}
Then in your component:
this.props.submitUserReview({ review, username: checkUsername(this.props.userData), uid })
Basically you were passing the function username to your submission, rather than running the function and passing the result of the function to submission. In this example, you define the check username function elsewhere to help with abstraction. And then in your submission you run the function and pass the result of it to your submitUserReview function.
Note that in JS, when you have a function:const x = () => 1, the type of x will be a function. As soon as you use the parenthesis, the function gets called: x(), and the value is returned. So in your original example, you were passing x as a parameter - which means that it was never evaluated and you passed a function into your store. You need to get the value out of it and pass that to redux.
This is good to know when binding a function to a component too. For example:
<Button onPress={this.doSomething()} />. In this case, the function doSomething will get evaluated when the Button is loaded, when you really want to evaluate it when it is tapped, like so: Button onPress={this.doSomething} />. In this case, onPress evaluates the function, so you don't need to do it yourself.
Another way to solve your problem is in the component where you render the username:
<Text>{review.username ? review.username : 'Anonymous'}</Text>
That conditionally shows username if it exists in a review object (or however it looks in your component), and shows Anonymous otherwise. This might be helpful if you need to tell whether or not the review actually has a username somewhere else.

You do not need to create funcion for this small thing. You can write it in below fashion:
this.props.submitUserReview({ review, username: (this.props.userData.username.username || "Anonymous"), uid });
Here if value of this.props.userData.username.username is falsy i.e. null OR undefined OR empty string then it will pass Anonymous as a parameter. Hence it will solve your usecase.

Related

Form Submit Iterating for Existing Username React

I'm trying to create a sign up page where it first iterates through existing accounts and submits when input account is available; otherwise, it returns an error message if just one element matches.
I first tried .map, but it iterates through the entire array and still submits if one value is false. I then tried .find, but still produces the same result. Afterwards, I tried switch, case and could only return the proper outcome with ==. Lastly, I tried .find and .map using .includes but, again, no luck.
function handleSubmit(e) {
e.preventDefault();
accounts.find(acc => {
if (acc.username.includes(formData.username)) {
console.log("taken");
} else {
some post request code
}
How can I create a function that only produces one outcome if one of many elements meets the condition? Thanks for the help
You should assign the function that finds or filters the username to a variable and then create an if statement using that variable.
To return the first matching object in the array of accounts
const matchingAccount = accounts.find(account => account.username.includes(formData.username);
To return an array of matching account objects
const matchingAccounts = accounts.filter(account => account.username.includes(formData.username);

setValue in a whole form with react-hook-form

I'm building up a user profile that has some addresses, the user can edit them, it's almost finished, but I'm stuck in setting the user edit address in a form.
Just like it shows in the GIF when I click the button no value is set, I'm using react-hook-form to build these forms.
This is the function that execute when I click on the button:
const editAddress = (i) => {
const addressClicked = addressList[i];
console.log(addressWatch());
setAddressValue("name", addressClicked);
setShowForm(true);
};
addressList is an array that is being looped, and then I get the key from the .map(v,i) and it returns an object with all the information that should populate the input fields for the user to edit it.
So, in the docs there is a function that is called "reset" that actually does exactly what I wanted, it wipes the current data from the form and it can replace with a new object data.
https://react-hook-form.com/api/useform/reset
The function looks like this now
const editAddress = (i) => {
const addressClicked = addressList[i];
addressReset(addressClicked);
setShowForm(true);
};

React-Redux mapStateToProps with dynamic (uid based) path

I am new to React and React-Redux. I'm trying to pass "mapStateToProps" using a dynamic pathway depending on the users id. The basic code being used follows:
const mapStateToProps = (state) => {
console.log(state);
console.log(state.firebase.auth.uid); <===== THIS DISPLAYS THE USERS ID, PROVING THE PATH EXISTS
return {
courses: `state.firestore.ordered.${state.firebase.auth.uid}`, <======= THIS LINE IS AN ERROR EVEN THOUGH THE PATH EXISTS
}
}
The code works fine if I manually type in the users ID. Lets say the users ID is "12345", then replacing that line with
courses: state.firestore.ordered.12345, <======= THIS LINE WOULD WORK
Any clarification as to why this doesn't work and an alternative method of making this work would be greatly appreciated!
If you want to access dynamic property in JS object, you need to use square braces
courses: state.firestore.ordered[state.firebase.auth.uid]

Shorten multiple lines of setState code in react

This question is just for the purpose of improving my codes in React which currently looks very dirty and unreadable. I have 10-15 forms field which updated once I get values from APIs.
Here is the code from which I did this,
this.setState({smtpServer:res.data.data[0].smtpServer});
this.setState({senderName:res.data.data[0].senderName});
this.setState({senderEmail:res.data.data[0].senderEmail});
this.setState({smtpPorts:res.data.data[0].smtpPort});
this.setState({username:res.data.data[0].username});
this.setState({password:res.data.data[0].password});
this.setState({authType:res.data.data[0].authType});
There is also lots more of setState method which I didn't add. This makes my component code complex. Is there any method to shorten these codes.
You can destructure the data and use a single setState with shorthand object assignment (i.e. keys are named the same as the variables)
const {
smtpServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType
} = res.data.data[0];
this.setState({
smtpServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType
});
Or, if res.data.data[0] has all the properties you want to store in state, more succinctly
this.setState({...res.data.data[0]});
You can shorten them by fitting it all into a single object state using setState. First try to destructure your res.data.data[0] object in order to handle the individual attributes better:
const { smptServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType} = res.data.data[0];
Next you can set state in one GIANT OBJECT with each attributes. ES6 allows javascript to use key only instead of key-value pairs when the key and value have the same name.
Thus: const objName = {username:username, password:password} can also be typed as
const objName = {username,password}
By that logic you can just setState as:
this.setState({ smptServer,
senderName,
senderEmail,
smtpPort,
username,
password,
authType});
Hope this helps.
Assuming these calls are happening in sequence, it could be written as
const data = res.data.data[0];
this.setState({
smtpServer: data.smtpServer,
senderName: data.senderName,
senderEmail: data.senderEmail,
smtpPorts: data.smtpPort,
username: data.username,
password: data.password,
authType: data.authType
});
Or if there's nothing else in that object, you could just simply do
this.setState(res.data.data[0]);
or
this.setState({ data: res.data.data[0] });
It can be achieved in a very simple way as below:
You can take that data in one variable and then you can assign it in the state.
const data = res.data.data[0];
this.setState({...data});
You can assign it directly without the use of an extra variable.
this.setState({...res.data.data[0]});

How to set the key name on an array in Angularfire

I am creating arrays using Angularfire but I am unable to set the key name. Firebase is automatically giving me a cryptic key (eg Jm9vLy8Lye-KS35KsmL) but I would like to set it myself to something more meaningful. It is unclear how I do this in Angularfire. I am using the $add method on $firebaseArray:
var firebaseRef = new Firebase("https://firebase_location");
$scope.messages = $firebaseArray(firebaseRef);
$scope.messages.$add(
{
FirstName: patient.FirstName,
LastName: patient.LastName
}
).then(function(firebaseRef) {
var id = firebaseRef.key();
});
The data is stored fine and I can see it on my dashboard. However, id is always a cryptic firebase value. I would love to be able to set it myself to something meaningful. In my case the individual patient's ID would be meaningful...
Any thoughts?
Thank you!
Thanks for the response.
I found that the child function will do what I need. I first specify the child and then set it.
var patient_child = firebaseScreenRef.child(patient.PatientId);
patient_child.set(
{
FirstName: patient.FirstName,
LastName: patient.LastName,
});
Adding an item to a firebase array make firebase define a unique id for you. If this is not what you want, I think you can try getting the "messages" object with $firebaseObject, instead of getting just the list with $firebaseArray. Then you will be able to edit your object in js, in order to add your items to the messages collection. In this way you can use the id that best suits your needs. Finally, you have to $save() your entire object. Look here: https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebaseobject
Hope this helps.
For your question, I found an explanation. You don't need to use firebaseObject, you should use ref directly:
var ref = new Firebase(FURL);
createProfile: function(id ,user) {
var profile = {`enter code here`
name: user.name,
email: user.email,
gravatar: get_gravatar(user.email, 40)
};
var profileRef = $firebaseArray(ref.child('profile').child(id));
return ref.child('profile').child(id).set(profile);
},
In the code, I use ref to reference my URL. With profileRef, I created a child profile and I added id for the profile. Afterwards, I use ref directly to set the value profile for the id that I want. You see, it is very easy.

Resources