Where do I add functions in React? - reactjs

I'm running through several tutorials, and I don't quiet undertand where I can write/put multiline functions?
Say I needed this filter function
const filter = {
address: 'England',
name: 'Mark'
};
let users = [{
name: 'John',
email: 'johnson#mail.com',
age: 25,
address: 'USA'
},
{
name: 'Tom',
email: 'tom#mail.com',
age: 35,
address: 'England'
},
{
name: 'Mark',
email: 'mark#mail.com',
age: 28,
address: 'England'
}
];
users= users.filter(item => {
for (let key in filter) {
if (item[key] === undefined || item[key] != filter[key])
return false;
}
return true;
});s
Where do I put it in React? Most tutorials are focused on App.js page, and the only thing i've learned was to add code here {in brackets}:
<div>
<h3> {1+1} </h3>
</div>
However, it doesn't make sense/looks bulky and unreadable to add the function above just inside there? Or is that the correct way? I'm currently focused on learning Javascript and frontend React only at the moment (not backend).

Here's an example of how you could use that function in React:
Define the function within the App.js file (inside the App component)
Call that function inside the JSX that you're returning
const App = () => {
const yourFunction = () => {
users.filter(function(item) {
for (var key in filter) {
if (item[key] === undefined || item[key] != filter[key])
return false;
}
return true;
});
}
return (
<div>
<h1>{yourFunction()}</h1>
</div>
);
}
It works the same way as putting javascript inside the JSX - it just runs what's inside the tags and in this case, that means running the function outside the returning JSX.

Related

How do you bind a dynamic API response to a React UI?

I am consuming an API which has a few 'required' fields and fields which are not required. As such, depending on the result of the response, the shape can change dramatically with fields being excluded in the response.
An example Schema:
{
name: string; // required
surname: string; // required
addresses: []
telephoneNumbers: []
gender: string; // required
age: number;
}
So a request could return multiple formats:
Example: 'api.com/users/123'
{
name: 'John',
surname: 'Doe',
addresses: [ ....]
telephoneNumbers: [....]
gender: 'male',
age: 20
}
Example: 'api.com/users/456
{
name: 'Betty',
surname: 'Boo',
gender: 'female',
}
When I bind the response to my UI (react) is there a way to check each field exists?
Do I have to check if each field exists and has a value in the response before rendering it? As in:
const DisplayResults = () => {
const { data } = await api.getUser('123');
return (
<div>
<div>{data.name}</div>
<div>{data.surname}</div>
{data.age && <div>{data.age}</div>}
{data.gender && <div>{data.age}</div>}
{data.addresses && <div>{data.addresses.map((address) => ...)}</div>}
</div>
)
}
Bear in mind any nested objects may have 'required' and non required fields which means I either need to sanitize the response to match the response to how I want or do a check on each field to make sure it's not undefined.
If I bind to a grid component, it'll throw errors for undefined fields which may or may not be there.
Any ideas?
Seems like depending on the type of data you need a different way to display the data.
You could create a piece of state which is an array of Objects that hold info on how to handle each key.
import React from 'react'
import ReactDOM from 'react-dom'
class User extends React.Component {
constructor(props) {
super(props);
this.state = {
user_rows: [
{
key_name: "name",
data_function: (data = "") => data,
display:(data) => data.length > 0 ? true : false
},
{
key_name: "addresses",
data_function:(data = []) => data.map((a,idx) => {
return( <div>{a}</div>)
}),
display:(data) => data.length > 0 ? true : false
},
{
key_name: "gender",
data_function:(data = "") => data,
display:(data) => data.length > 0 ? true : false
}
]
}
}
render() {
let data = {
name: 'John',
surname: 'Doe',
addresses: ["adress 1"],
telephoneNumbers: ["000 000 000"],
gender: '',
age: 20
}
return (
<div>
{this.state.user_rows.map((ur,idx) => (
ur.display && <div key={idx}>{ur.data_function(data[ur.key_name])}</div>
))}
</div>
);
}
}
ReactDOM.render(
<User/>,
document.getElementById('container')
);

Functional component problems React

I transformed a class component into a functional component but it looks like it does not work in a way it suppose to work and I can not find what is wrong. When I create a new object there is no name for the object and when I try to mark the object as a complete it removes all created objects at ones. I created a codesandbox here. Unfortunately, I am not too much familiar with functional component. Any help would be appreciated.
Here is my codesandbox sample:
https://codesandbox.io/s/crazy-sid-09myu?file=/src/App.js
Your Todos:
const [todos, setTodos] = useState([
{ id: uuid(), name: "Task 1", complete: true },
{ id: uuid(), name: "Task 2", complete: false }
]);
onAddHandler:
const addTodo = () =>
setTodos([...todos, { id: uuid(), name: "New Task", complete: false }]);
onSetCompleteHandler:
const setCompleteHandler = id =>
setTodos(
todos.map(todo => {
if (todo.id === id) {
return {
...todo,
complete: todo.complete ? 0 : 1
};
}
return todo;
})
);
I have created your new todos. Check out this link
Todos App
I have updated your code, please check the URL https://codesandbox.io/s/determined-morning-n8lgx?file=/src/App.js
const onComp = id => {
for (let i = 0; i < todos.length; i++) {
if (todos[i].id === id) {
let t = { ...todos[i] };
t.complete = !t.complete;
todos[i] = t;
}
}
setTodos([...todos]); // Here todos reference need to be changed
};
And also
const onSubmit = event => {
event.preventDefault();
setTodos([
...todos,
{
id: generateNewId(),
name: newTodoName,
complete: false
}
]);
setNewTodoName("");
};
While using hooks we need to be careful about state variable updates. While manipulating arrays and objects use the spread operator to create new references which invokes child components and re-render current component.

How to build an array using form values in Angular

I have the function in the component as below:
updateInfo(info: NgForm) {
const changedValues = Object.keys(info.controls)
.filter(key => info.controls[key].dirty === true)
.map(key => {
return { control: key, value: info.controls[key].value }
});
console.log(changedValues);
}
This function emits the changes form values, but now I want to build an array using changedValues as below:
{
firstName: "john",
lastName: "sam"
}
How could I implement it?
Edit: currently I'm getting like this in the console log
[
{firstName: "john"},
{lastName: "sam"}
]
Don't use map because that returns an array. Instead use forEach and add the items to your object:
updateInfo(info: NgForm) {
const changedValues = {};
Object.keys(info.controls).forEach(key => {
if (info.controls[key].dirty) {
changedValues[key] = info.controls[key].value;
}
});
console.log(changedValues);
}

Adding to an array within an array state in ReactJS

I'm trying to add functionality for adding to a state, more specifically "list", in the following state:
shoeList : [
{name: 'Nike',
list : [
{type: 'boots', revenue: '1000000', gender: 'mens', price: '49.99', id: 3},
{type: 'shoes', revenue: '13280100', gender: 'womens', price: '99.99', id: 2}
]
}
],
Right now I have a component that displays a form for the user to enter new values for type revenue gender and price.
Here is the code for the component(not including the forms and text input html):
state = {
}
//when changes occur in text input fields
handleChange = (e) => {
this.setState({
[e.target.id]: e.target.value
})
}
handleSubmit = (e) => {
e.preventDefault();
this.props.addShoe(this.state);
And in the root component i have the addShoe function:
addShoe = (shoe) => {
shoe.list.id = Math.random();
//returns a new array so no alteration of original array
let shoeList = [...this.state.shoeList, shoe];
this.setState({
shoeList: shoeList
})
}
Trying this code gives me an error saying shoe.list.id is undefined? Also I think I'm missing something to add in the component file specifically in the state. Also is there any way to directly access list like this.state.shoeList.list? I'm not sure if i have to add list to shoeList. Any help would be great thanks
In your example, if the intention is to add an item to specifically the Nike list:
addShoe = (shoe) => {
this.setState({
// return an altered copy of the array via map
shoeList: this.state.shoeList.map(brandItem => {
if (brandItem.name === 'Nike') {
return {
// use spread syntax for other object properties to persist
...brandItem,
list: [
// use spread syntax to keep the original items in the list
...brandItem.list,
{
// assuming shoe is an object without an id property
...shoe,
id: Math.random()
}
]
}
} else {
return brandItem;
}
})
}

Make a common function to store the local storage data

I am a newbie in react-native. I have a folder structure like below:
-screens
-page1.js
-page2.js
-page3.js
-page4.js
-App.js
In page1.js, I have a function to store data to localStorage
let obj = {
name: 'John Doe',
email: 'test#email.com',
city: 'Singapore'
}
AsyncStorage.setItem('user', JSON.stringify(obj));
Now I have to display these data in few of my other pages. This is my code.
class Page2 extends Component {
state = {
username: false
};
async componentDidMount() {
const usernameGet = await AsyncStorage.getItem('user');
let parsed = JSON.parse(usernameGet);
if (parsed) {
this.setState({
username: parsed.name,
email: parsed.email
});
} else {
this.setState({
username: false,
email: false
});
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.saved}>
{this.state.username}
</Text>
</View>
);
}
}
export default Page2;
This is how I display data in page2. I may need to show these in other page too.
I dont want to repeat these codes in each page.
Any suggestions how to do it in react-native?
You can extract the data you need to display into it's own component and re-use it in any page that you need to display it in.
Another option is to use a higher-order component, that way you can wrap it around any components that need the data and it'll be passed down as a prop.
You can make your Constant.js where you can put all your common required utils and constants, reusable anywhere n your app.
In your Constant.js:
export const USER_DATA = {
set: ({ user}) => {
localStorage.setItem('user', JSON.stringify(obj));
},
remove: () => {
localStorage.removeItem('user');
localStorage.removeItem('refresh_token');
},
get: () => ({
user: localStorage.getItem('user'),
}),
}
in your any component, you can import it and use like this :
import { USER_DATA } from './Constants';
let user = {
name: 'John Doe',
email: 'test#email.com',
city: 'Singapore'
}
// set LocalStorage
USER_DATA.set(user);
// get LocalStorage
USER_DATA.get().user
That's you can make Constant common file and reuse them anywhere to avoid writing redundant code.
Simplified Reusable approach of localStorage
export const localData = {
add(key, value) {
localStorage.setItem(key, JSON.stringify(value));
},
remove(key, value) {
localStorage.removeItem(key);
},
load(key) {
const stored = localStorage.getItem(key);
return stored == null ? undefined : JSON.parse(stored);
},
};
localData.add("user_name", "serialCoder")
console.log( "After set 👉", localData.load("user_name") )
localData.remove("user_name")
console.log( "After remove 👉", localData.load("user_name") )

Resources