Week Picker In Reactjs and display week like a table with seven days and dates - ecmascript-2016

Use Reactjs and it needs prev and next buttons.
By clicking on the prev button it should go previous week
By clicking on the next button it should go next week
I'm new to Reactjs and I request please anyone helps me out
example
< date-month-year to date-month-year > of a week

Date math is complicated. You can go with something like Moment or Luxon for handling this sort of thing. I like date-fns because it abstracts dealing with the native JS Date object, handling all the basics. Here's an example in a React hook.
// useNextPrevToday
import { useState } from 'react';
import add from 'date-fns/add';
import sub from 'date-fns/sub';
const PERIODS = ['year', 'month', 'week', 'day', 'hour', 'minute'];
export default function () {
const [now, setNow] = useState(DateTime.local());
const checkPeriod = function (period) {
if (!PERIODS.includes(period)) {
throw new Error(`The period ${period} is not valid. Use 'year', 'month', 'week', 'day', 'hour' or 'minute'.`);
}
};
const next = function (period = 'day') {
checkPeriod(period);
setNow((prev) => add(prev, { [`${period}s`]: 1 }));
};
const previous = function (period = 'day') {
checkPeriod(period);
setNow((prev) => sub(prev, { [`${period}s`]: 1 }));
};
const today = function () {
setNow(new Date());
};
return {
next,
previous,
today,
now,
};
}
Then use it
// DateDisplay
import React from 'react';
import useNextPreviousToday from './useNextPreviousToday'
export const DateDisplay = function () {
const [next, previous, today, now] = useNextPreviousToday();
return (
<div>
<button onClick={() => previous('day')}>Previous</button>
<button onClick={() => today()}>Today</button>
<button onClick={() => next('day')}>Next</button>
</div>
<div>
{now.toString()}
</div>
)
};
This is a really rough example, but should point you where you need to go.

Related

Display date from Firestore React native

I try to display the picked event date för my posts from Firestore using moment. Right now it just print The current day, so I display the date but not ont he right way. I get no error message. I have tried to change the timestamp to "dateUpload". but it gives me a print in my Text component "invalid date". Do any have clue of what I can do?
This is how display it my flatlist:
postDate={moment(item.timestamp).format("ll")}
In my redux Action.js
export function fetchFollowingUsersPosts(uid) {
return ((dispatch, getState) => {
firebase.firestore()
.collection("posts")
.doc(uid)
.collection("userPosts")
.orderBy("creation", "asc")
.get()
.then((snapshot) => {
const uid = snapshot.query.EP.path.segments[1];
const user = getState().usersState.users.find(el => el.uid === uid);
const posts = snapshot.docs.map((doc) => {
const { data: firebaseTimestamp, ...rest } = doc.data()
const id = doc.id;
const data = firebaseTimestamp ? moment(firebaseTimestamp.toDate()) : null
return {
...rest,
id,
user,
...data
}
})
//console.log(posts);
dispatch({ type: USERS_POSTS_STATE_CHANGE, posts, uid, })
})
})
}
Image on my database:
Instead of const data = firebaseTimestamp ? moment(firebaseTimestamp.toDate()) : null, try this const data = firebaseTimestamp ? firebaseTimestamp.toDate() : null , so you'll be having a javascript Date object, instead of a Moment object.
Then, you can use it as you did postDate={moment(item.timestamp).format("ll")}, assuming that item.timestamp is the Date object from above

React Native how to set the time and date as the local device?

I was trying to get the time and date and set as the local device format .
I have tried this api "https://www.npmjs.com/package/react-native-device-time-format?activeTab=readme",
But dosen't work at all ..
Here is my code ,could you please take a look ?
Thank you so much ?
import React,{useEffect,useState} from 'react';
import { StyleSheet, View } from 'react-native';
import { is24HourFormat } from 'react-native-device-time-format';
import moment from 'moment';
function TryTime(props) {
const [currentTime, setCurrentTime] = useState("");
const getCurrentHourFormat = async (date) => {
const is24Hour = await is24HourFormat();
return moment(date).format(is24Hour ? 'HH:mm' : 'h:mm A');
}
useEffect(() => {
(async () => {
const timeNow = await TryTime(Date.now);
setCurrentTime(getCurrentHourFormat(timeNow));
})();
}, []);
return (
<View style={styles.container}>
<Text>{currentTime}</Text>
</View>
);
}
const styles = StyleSheet.create({
container : {
flex : 1,
justifyContent : 'center',
alignItems : 'center',
}
})
export default TryTime;
First, to get the local time of device by JS, you can use a built-in function of js: toLocaleString()
Note:
For this question: Do you know how to get more simple ? Something like 1 sec ago ,10 min ago ,1 hour ago
=> i guess you have the previous date time, and you want to compare it to current time
something like:
a = ... // your previous time
b = new Date().toLocaleString()
Just take let c = b - a as the difference between 2 date, then
c / 1000 => get seconds
c / 1000 * 60 => get minutes
c / 1000 * 3600 => get hours

How to do jest testing in react native?

I have a simple code which I have written to test.
This is my App.js:
const App: () => React$Node = () => {
function sum(a, b) {
alert(a + b);
return a + b;
}
return (
<>
<Button
title="Sum"
onPress={() => {sum(1,2)}}
/>
);
This is my App-test.js in the __tests__ folder:
import 'react-native';
const sum = require('../App');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
When I run npm test I get this error TypeError: sum is not a function. Can anyone help.
Note: When I run it on my android phone it works properly and shows 3 in the alert box.
It's because you are importing sum from your App file but it is not an exported method the way you wrote it.
You can do something like this:
export const sum = (a, b) => {
alert(a + b);
return a + b;
}
export const App = () => (
<Button
title="Sum"
onPress={() => {sum(1,2)}}
/>
);
And use it like this in your test file:
import { sum } from '../App'
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
It's not particularly linked to React Native since you're only trying to test a specific method, which can be use with any framework.

Vue composition api - component doesnt render at start using reactive()

Just started using Vue composition-api (with Vue2) and I ran into some reactivity? problem.
In the template, I want to render list of elements based on selected date.
My template:
...
<div v-for="(act, idx) in elementsPerDay[dateMatchable]" :key="idx">
...some content...
</div>
...
Now the problem is that when the component is created and data are fetched, nothing is rendered and elementsPerDay are empty (in the template). Once I force template update (for example by calling vm.$forceUpdate()) everything works fine.
My setup:
...
const selectedDate = new Date()
const { data } = <async function to get data>
const dateMatchable = computed(() => formatDate(selectedDate, 'YYYY-MM-DD')) // returns selectedDate as YYYY-MM-DD
// Here I init my reactive object
const elementsPerDay = reactive({})
// Here I fill my elementsPerDay when data changes (basically grouping data by day)
watch(data, e => {
const elsPerDay = {}
for (let idx = 0; idx < data.length; idx++) {
const element = data[idx]
const elementDate = formatDate(data.datetime, 'YYYY-MM-DD')
if (elementsPerDay[elementDate] === undefined) {
elsPerDay[elementDate] = []
}
elsPerDay[elementDate].push(act)
})
// Assign data to my reactive object
Object.assign(elementsPerDay, elsPerDay)
})
...
return { ..., selectedDate, dateMatchable, elementsPerDay }
EDIT:
Using computed works:
const elementsPerDay = computed(() => {
if (!data.value) {
return {}
}
const elsPerDay = {}
for (let idx = 0; idx < data.value.length; idx++) {
const element = data.value[idx]
const elementDate = formatDate(element.datetime, 'YYYY-MM-DD')
if (elsPerDay[elementDate] === undefined) {
elsPerDay[elementDate] = []
}
elsPerDay[elementDate].push(element)
}
return elsPerDay
})
I realize that in Options API, you needed to $set() new fields in object for it to be reactive but I thought that reactive() somehow does this for me. Am i wrong?
Compoisition API plugin is not Vue 3. Actually, what you encounter is a limitation from Vue 2 : https://v2.vuejs.org/v2/guide/reactivity.html#For-Objects.
You need to use $set.
I found an issue about your problem on Github: https://github.com/vuejs/composition-api/issues/334.
If you're using https://github.com/vuejs/composition-api, you can use $set() by:
import { set } from '#vue/composition-api'
...
setup() {
set(object, 'key', 'value');
}

Crash with simple history push

just trying come silly stuff and playing around with Cycle.js. and running into problem. Basically I just have a button. When you click it it's suppose to navigate the location to a random hash and display it. Almost like a stupid router w/o predefined routes. Ie. routes are dynamic. Again this isn't anything practical I am just messing with some stuff and trying to learn Cycle.js. But the code below crashes after I click "Add" button. However the location is updated. If I actually just navigate to "#/asdf" it displays the correct content with "Hash: #/asdf". Not sure why the flow is crashing with error:
render-dom.js:242 TypeError: Cannot read property 'subscribe' of undefined(…)
import Rx from 'rx';
import Cycle from '#cycle/core';
import { div, p, button, makeDOMDriver } from '#cycle/dom';
import { createHashHistory } from 'history';
import ranomdstring from 'randomstring';
const history = createHashHistory({ queryKey: false });
function CreateButton({ DOM }) {
const create$ = DOM.select('.create-button').events('click')
.map(() => {
return ranomdstring.generate(10);
}).startWith(null);
const vtree$ = create$.map(rs => rs ?
history.push(`/${rs}`) :
button('.create-button .btn .btn-default', 'Add')
);
return { DOM: vtree$ };
}
function main(sources) {
const hash = location.hash;
const DOM = sources.DOM;
const vtree$ = hash ?
Rx.Observable.of(
div([
p(`Hash: ${hash}`)
])
) :
CreateButton({ DOM }).DOM;
return {
DOM: vtree$
};
}
Cycle.run(main, {
DOM: makeDOMDriver('#main-container')
});
Thank you for the help
I would further suggest using #cycle/history to do your route changing
(Only showing relevant parts)
import {makeHistoryDriver} from '#cycle/history'
import {createHashHistory} from 'history'
function main(sources) {
...
return {history: Rx.Observable.just('/some/route') } // a stream of urls
}
const history = createHashHistory({ queryKey: false })
Cycle.run(main, {
DOM: makeDOMDriver('#main-container'),
history: makeHistoryDriver(history),
})
On your function CreateButton you are mapping your clicks to history.push() instead of mapping it to a vtree which causes the error:
function CreateButton({ DOM }) {
...
const vtree$ = create$.map(rs => rs
? history.push(`/${rs}`) // <-- not a vtree
: button('.create-button .btn .btn-default', 'Add')
);
...
}
Instead you could use the do operator to perform the hashchange:
function CreateButton({ DOM }) {
const create$ =
...
.do(history.push(`/${rs}`)); // <-- here
const vtree$ = Observable.of(
button('.create-button .btn .btn-default', 'Add')
);
...
}
However in functional programming you should not perform side effects on you app logic, every function must remain pure. Instead, all side effects should be handled by drivers. To learn more take a look at the drivers section on Cycle's documentation
To see a working driver jump at the end of the message.
Moreover on your main function you were not using streams to render your vtree. It would have not been reactive to locationHash changes because vtree$ = hash ? ... : ... is only evaluated once on app bootstrapping (when the main function is evaluated and "wires" every streams together).
An improvement will be to declare your main's vtree$ as following while keeping the same logic:
const vtree$ = hash$.map((hash) => hash ? ... : ...)
Here is a complete solution with a small locationHash driver:
import Rx from 'rx';
import Cycle from '#cycle/core';
import { div, p, button, makeDOMDriver } from '#cycle/dom';
import { createHashHistory } from 'history';
import randomstring from 'randomstring';
function makeLocationHashDriver (params) {
const history = createHashHistory(params);
return (routeChange$) => {
routeChange$
.filter(hash => {
const currentHash = location.hash.replace(/^#?\//g, '')
return hash && hash !== currentHash
})
.subscribe(hash => history.push(`/${hash}`));
return Rx.Observable.fromEvent(window, 'hashchange')
.startWith({})
.map(_ => location.hash);
}
}
function CreateButton({ DOM }) {
const create$ = DOM.select('.create-button').events('click')
.map(() => randomstring.generate(10))
.startWith(null);
const vtree$ = Rx.Observable.of(
button('.create-button .btn .btn-default', 'Add')
);
return { DOM: vtree$, routeChange$: create$ };
}
function main({ DOM, hash }) {
const button = CreateButton({ DOM })
const vtree$ = hash.map(hash => hash
? Rx.Observable.of(
div([
p(`Hash: ${hash}`)
])
)
: button.DOM
)
return {
DOM: vtree$,
hash: button.routeChange$
};
}
Cycle.run(main, {
DOM: makeDOMDriver('#main-container'),
hash: makeLocationHashDriver({ queryKey: false })
});
PS: there is a typo in your randomstring function name, I fixed it in my example.