How to use the TabNavigator of the react navigation in ClojureScript? It's really difficult to write navigationOption configuration and I want to know how to reach it.
I have do some efforts to address it, but not suitable. I have learned the mechanism of clojure compiler, so I try best to avoid the rookie mistakes.But it's really difficult to solve the problem of
anonymous function as the prop to some components. If you write them using fn, #(...), the propname will changed when compiled to js.
THe javascript code shows as following:
const TabNavigator = createBottomTabNavigator({
HomeScreen: {
screen: HomeScreen,
navigationOptions:({naviagtion}) => ({
tabBarLabel: 'home',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./assets/home.png')}
selectedImage={require('./assets/home.png')}
/>
)
})
},
Content: {
screen: content,
navigationOptions:({naviagtion}) => ({
tabBarLabel: 'content',
tabBarIcon: ({focused, tintColor}) => (
<TabBarItem
tintColor={tintColor}
focused={focused}
normalImage={require('./assets/content.png')}
selectedImage={require('./assets/content.png')}
/>
)
})
}
},
{
tabBarOptions: {
activeTintColor: '#4CB4E7',
inactiveTintColor: '#FFEE93',
style: {backgroundColor: '#FFC09F'}
}
})
And this is my trying:
(defn tab-navigator []
(router/create-bottom-tabnavigator
(clj->js {:HomeScreen
(clj->js {:screen (r/reactify-component home-screen)
:navigationOptions (fn [{:keys [navigation]}]
(clj->js {:tabBarLabel "home"
:tabBarIcon (fn [{:keys [focused, tintColor]}]
(tabbar/tab-bar-item tintColor focused (js/require "../resources/assets/home.png") (js/require "../resources/assets/home.png")))}))})
:Content
(clj->js {:screen (r/reactify-component content/content)
:navigationOptions (fn [{:keys [navigation]}]
(clj->js {:tabBarLabel "conent"
:tabBarIcon (fn [{:keys [focused, tintColor]}]
(tabbar/tab-bar-item tintColor focused (js/require "../resources/assets/content.png") (js/require "../resources/assets/content.png")))}))})})
(clj->js {:tabBarOptions
{:activeTintColor "#4CB4E7"
:inactiveTintColor "#FFEE93"
:style {:backgroundColor "#FFC09F"}}
})))
Please give me a approach or some archive to refer, It's a really big gift.
I see two things :
You should use clj->js only before the first map
You should pass a map for the tabbar/tab-bar-item's properties
I use something like that for projects :
(defn tab-navigator []
(router/create-bottom-tabnavigator
(clj->js {:HomeScreen {:screen (r/reactify-component home-screen)
:navigationOptions
{:tabBarLabel "home"
:tabBarIcon (fn [{:keys [focused tintColor]}]
(tabbar/tab-bar-item
{:tintColor tintColor
:focused focused
:normalImage (r/as-element [:> rn/Image {:source (js/require "../resources/assets/home.png")}])}))}}})
(clj->js {:tabBarOptions
{:activeTintColor "#4CB4E7"
:inactiveTintColor "#FFEE93"
:style {:backgroundColor "#FFC09F"}}})))
Related
I do create POO pattern in cypress with elements and actions and the code works but sonatype is throwing up a error but i dot know why
elements = { //error here E054: Class properties must be methods. Expected '(' but instead saw '='.
tittle: () => cy.contains("Welcome to the Reside Resident Experience"),//error here E030: Expected an identifier and instead saw '=>'.
inputFirstName: () => cy.get('input[data-test-id="resident_firstName"]'),
inputLastName: () => cy.get('input[data-test-id="resident_lastName"]'),
inputMonth: () =>cy.get('input[data-test-id="dob-month-resident_dateOfBirth"]'),
};
//#endregion
//#region Actions
isLoaded() {
this.elements.tittle().should("exist");
}
I am trying to navigate to a nested stack, when I use navigation.push(AppRoutes.RescueMeLanding.Name) I get the error:
Couldn't find a 'component', 'getComponent' or 'children' prop for the screen 'RescueMeStackScreen'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.
Any ideas?
const AppRoutes = {
....
RescueMeLanding: {
Name: 'RescueMeStackScreen',
Label: 'Rescue Me',
isProtected: true,
},
....
};
RescueMeStackScreen:
const RescueMeStackScreen = () => {
return (
<RescueMeStack.Navigator
initialRouteName={AppRoutes.RescueMeLanding.Name}
>
<RescueMeStack.Screen
name={AppRoutes.RescueMeLanding.Name}
component={RescueMeLandingScreen}
options={{ headerShown: false }}
/>
<RescueMeStack.Screen
name={AppRoutes.RescueMeMap.Name}
component={RescueMeScreen}
options={{ headerShown: false }}
/>
;
</RescueMeStack.Navigator>
);
RootStackNavigator:
const RootStackNavigator = () => {
return (
<RootStack.Navigator
initialRouteName={AppRoutes.LoginRegistration.Name}
mode="modal"
>
....
<RootStack.Screen
name={AppRoutes.RescueMeLanding.Name}
component={RescueMeStackScreen}
options={{
title: AppRoutes.Register.Label,
headerShown: false,
animationEnabled: false,
}}
/>
....
</RootStack.Navigator>
);
When navigating to nested component, you need to specify parent explicitly.
See this for further information.
Thus, in your case;
navigation.push(AppRoutes.RescueMeLanding, { screen: AppRoutes.RescueMeLanding.Name })
What I also would suggest is name stack differently than the screen. Such as;
navigation.push(AppRoutes.RescueMeLandingStack, { screen: AppRoutes.RescueMeLanding.Name })
I have a object config where I send a function callback to a function.
test('should create a ComponentMockwith the needed config', () => {
const config: MyConfig = {
// more options
myCallback: jasmine.anything()
};
sut.doYourThing(config);
expect(ComponentMock.create).toHaveBeenCalledWith(config);
});
The problem I have is that after an update to the latest jest/jasmine I get this error in myCallback: jasmine.anything():
How to fix Type 'AsymmetricMatcher' is not assignable to type '() => void'. in jasmine/jest
If I ignore that line with #ts-ignore my test keeps working but I want to know why is the linter saying that and how to fix it since I really do not understand it.
I had same issue in my app, I have solved it by mapping troublesome type to any jasmine.anything() as any. Maybe it will solve your problem as well.
test('should create a ComponentMockwith the needed config', () => {
const config: EqListeningPlayerConfig = {
// more options
myCallback: jasmine.anything() as any // < --- here is what solved my issue
};
sut.doYourThing(config);
expect(ComponentMock.create).toHaveBeenCalledWith(config);
});
I was trying to understand if RxJS would be a good fit for solving the problem that this node module performs: https://github.com/ericdolson/debouncing-batch-queue
It's description says: "A queue which will emit and clear its contents when its size or timeout is reached. Ideal for aggregating data for bulk apis where batching in a timely manner is best. Or anything really where batching data is needed."
If so, could someone walk me through how to implement the simple example in this npm module with RxJS? Ideally with ES5 if possible.
There's an operator for that™: bufferwithtimeorcount. If you need it to be truly equivalent, the input stream would be a Subject, with group_by for namespaces, like the following:
var dbbq$ = new Subject();
dbbq$.group_by(function(v_ns) { return v_ns[1]; })
.flatMap(function(S) {
return S.bufferwithtimeorcount(1000, 2)
});
dbbq$.next([ 'ribs 0' ]);
dbbq$.next([ 'more ribs', 'bbq1' ]);
// is analogous to
var dbbq = new DBBQ(1000, 2);
dbbq.add('ribs 0');
dbbq.add('more ribs', 'bbq1');
No way I'm doing this with ES5 :)
const dataWithNamespace = (data, namespace) => ({data, namespace});
const source = [
dataWithNamespace('ribs 0'),
dataWithNamespace('ribs 1'),
dataWithNamespace('ribs 2'),
dataWithNamespace('ribs 3'),
dataWithNamespace('ribs 4'),
dataWithNamespace('more ribs', 'bbq1'),
dataWithNamespace('more ribs', 'bbq1'),
dataWithNamespace('brisket', 'best bbq namespace')
];
const DBBQ = (debounceTimeout, maxBatchSize) =>
source$ => source$
.groupBy(x => x.namespace)
.mergeMap(grouped$ => grouped$
.switchMap(x =>
Rx.Observable.of(x.data)
.concat(Rx.Observable.of(undefined)
.delay(debounceTimeout)
)
)
.bufferCount(maxBatchSize)
.filter(x => x.length == maxBatchSize)
.map(x => x.filter(x => x !== undefined))
);
const source$ = Rx.Observable.from(source);
DBBQ(1000, 2)(source$).subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.js"></script>
This is related to another question I posted here, but it's still boggling my mind.
I have a simple backbone model instance, called searchResult that I have working great within my view.
What I'm basically trying to do is simple; reset the an area of content inside the view as this model changes.
For some reason, when I'm inside a the view, this code doesn't seem to work correctly, though it seems it should:
View Code:
define [
'backbone.marionette',
"jquery",
"underscore",
"backbone",
'text!globalTemplates/sidebar.html',
"global/models/sidebar",
"global/views/categories",
"global/collections/categories",
"global/views/stores",
"global/collections/stores",
'search/models/search-results'
], (Marionette, $, _, Backbone, SidebarTemplate, SidebarModel, categoriesView, categoriesCollection, storesView, storesCollection, SearchResult) ->
class SidebarLayout extends Marionette.Layout
template: _.template SidebarTemplate
id: 'sidebar'
className: 'js-sidebar marionette-layout'
tagName: 'aside'
regions:
form: 'form'
categoriesList: '#categories-list'
storesList: '#stores-list'
ui:
searchInput: "input.search"
logo: "strong#logo a"
lower: ".lower"
top: ".top"
events:
"click strong#logo a": "goHome"
"submit .top form": "search"
"click button.submit": "search"
# "keyup input.search": "quickSearch"
initialize: (opts) ->
#router = opts.router
# event triggers
#on "sidebar:finished", #resize, #
# override the categories display event
#categoriesList.open = (view) ->
this.$el.hide()
this.$el.html(view.el)
this.$el.slideDown(250, "easeOutExpo")
# override the stores display event
#storesList.open = (view) ->
this.$el.hide()
this.$el.html(view.el)
this.$el.slideDown(250, "easeOutExpo")
# override the categories remove event
#categoriesList.remove = (view) ->
this.$el.html(view.el)
this.$el.slideUp(250, "easeOutExpo", -> $(this).remove())
# override the stores display event
#storesList.remove = (view) ->
console.log 'stores remove'
this.$el.slideUp(250, "easeOutExpo", -> $(this).remove())
globalListeners: ->
# bind app vent and other global handlers
# app.vent.on "search:setParams", #setSearchInput
# SearchResult.on "change:params", #setSidebar, #
# bind to changes to search params.
# SearchResult.listenTo #, "change:params", #setSidebar()
SearchResult.listenTo #, "change", #setSidebar()
# SearchResult.on "change:params", #render, #
resize: =>
sidebarHeight = #$el.height()
topHeight = #ui.top.height()
#ui.lower.height(sidebarHeight - topHeight)
setSidebar: (input=true) =>
# console.dir "SidebarLayout: setSidebarContent"
if input then #setSearchInput()
if SearchResult.get("params")
switch SearchResult.get("params").type
when "categories"
#setCategories()
when "text"
#setStores()
#setCategories()
setSearchInput: ->
if SearchResult.get("params")?
searchTerm = SearchResult.get("query")
#ui.searchInput.attr("value", searchTerm)
else
#ui.searchInput.attr("value", "")
setStores: ->
stores = new storesCollection()
stores.fetch
success: =>
#storesView = new storesView
collection: stores
#storesList.show #storesView
#storesList.$el.prev("h3").show()
#trigger "sidebar:finished"
setCategories: ->
# console.log 'SidebarLayout: setCategories'
categories = new categoriesCollection()
categories.fetch
success: =>
#categoriesView = new categoriesView
collection: categories
#categoriesList.show #categoriesView
#categoriesList.$el.prev("h3").show()
#trigger "sidebar:finished"
reset: =>
#$el.css
"opacity": 0
"margin-left": "-500px"
slideSidebarIn: =>
#$el
.animate
"opacity":1
"margin-left":0
, 500, -> app.reqres.setHandler "sidebar:visible", -> true
# CUSTOM EVENTS
goHome: (e) =>
e.preventDefault()
# #router.navigate "/", trigger: true
# we're going to avoid using navigate,
# too complex to refactor at this point
window.location = "/"
quickSearch: =>
# not working yet.
value = #ui.searchInput.val()
SearchResult.set("value", value)
search: (e) =>
e.preventDefault()
value = #ui.searchInput.val()
app.router.navigate "search/#{value}?type=text", trigger: true
onBeforeRender: =>
unless app.request("sidebar:visible") is true
#reset()
onRender: =>
# console.dir 'SidebarLayout: render'
setTimeout =>
#bindUIElements()
#globalListeners()
, 50
#$el.removeClass("hide")
if app.request("sidebar:visible") is false
#slideSidebarIn()
The issue is with this line:
searchResult.on "change:params", #setSidebarContent, #
I get this error:
Uncaught TypeError: Cannot call method 'show' of undefined
I'm assuming this has something to do with the region not being defined, or a relevant context not being passed through.
So, after tons of research and about 5 hours of nonsense, I read up on the docs for listenTo and it seems this code should work:
#listenTo searchResult, "change:params", #setSidebarContent()
The only way I was actually able to get it working, however, was to do this exact code:
searchResult.listenTo #, "change:params", #setSidebarContent()
So, I have it working now, and beautifully. I'm just confused why on earth I had to pass it through this way and why that first way didn't seem to work?
Remove the () after #setSidebarContent - this has gotten me in the past too.
#listenTo searchResult, "change:params", #setSidebarContent