React Native: How do I style NavigationExperimental's NavigationCardStack and NavigationHeader? - javascript

I am trying to change the background color of NavigationExperimental's NavigationCardStack by: style={{backgroundColor:'white'}} but it does not work.
Is there a way around it? Or is it not possible?
Also, how can I hide the NavigationHeader's 1px hairline? I tried doing shadowHidden={true} but it is not provided unfortunately.

Your style prop is correct. But where are you applying it? You should apply this prop to NavigationHeader.
<NavigationHeader
style={{backgroundColor:'blue'}}
...
You are probably rendering the NavigationHeader in a separate function, maybe named renderHeader(). This function is passed as a prop to NavigationCardStack
<NavigationCardStack
onNavigateBack={this.props.onNavigateBack}
renderHeader={this.renderHeader}
...
edit: answer to the question about the hairline:
style={{backgroundColor:'blue', borderBottomWidth: 0}}
Here is the RN code for the hairline style, as you can see it's platform dependent:
borderBottomWidth: Platform.OS === 'ios' ? StyleSheet.hairlineWidth : 0,

Related

NextJS conditional CSS?

Came across this when creating an animated dropdown for a navbar.
In a strict React implementation, an inline if/else statement can be used with an onClick toggle to set and remove CSS animation styles. In order to provide a default styling (with no animation) for when state is null, a class can be added before the inline if/else operation:
<div className={`navbar ${reactState ? "expanded" : "collapsed"}`}>
How do I replicate this in NextJS?
I can't find anything in the documentation and have blindly attempted the following (unsuccessfully):
<div className={styles.navbar (reactState ? `${styles.expanded}` : `${styles.collapsed}`)}>
<div className={styles.navbar [reactState ? `${styles.expanded}` : `${styles.collapsed}`]}>
<div className={styles.navbar `${reactState ? `${styles.expanded}` : `${styles.collapsed}`}`}>
The only success I've had is with the following, which seems like overkill:
<div className={
reactState != null ?
(reactState ? `${styles.navbar} ${styles.expanded}`
: `${styles.navbar} ${styles.collapsed}`)
: styles.navbar
}>
I'm clearly not fully understanding how NextJS handles React styling. Any help would be appreciated.
This should work, and it works as same as React. Only you didn't escape the values correctly.
<div className={`${styles.navbar} ${reactState ? styles.expanded : styles.collapsed}`}>...</div>

Conditionally render border colour React Native

I'm trying to conditionally change my border color based on whether the textInput is under focus or not.
<View
style={focus? { ...styles.inputRow, ...bgColorOnFocus }: { ...styles.inputRow, ...bgColorOnBlur }}>
This works as expected, but I'm having to repeat inputRow styles twice. I've been trying to improve the code with the following code where I add the object based on whether it's on focus or not and it's throwing an error.
<View style ={
{...styles.inputRow, focus? ...bgColorOnFocus: ...bgColorOnBlur}}
>
I'm not sure if I'm being silly, or if there's something missing that I'm not familiar with? Thanks for looking into this!
Typically a style prop accept an array as a value:
<View style={[styles.inputRow, isFocus ? bgColorOnFocus : bgColorOnBlur]}>
is a valid way to conditionally render some style.

render simple HTML with react.cloneElement

React.cloneElement() always require first parameter as react component which should be passed as children in props.
Is there are way to pass a simple HTML node as a children. Please refer the code below for better understanding of my issue:
Dialog.jsx (Common component):
return (
<div className="app-dialog-jsx" ref={(ele) => this.ele = ele}>
{this.state.show && React.cloneElement(this.props.children, {
contentStyle: {
height: 400,
overflowY: 'auto',
overflowX: 'hidden'
},
method1: this. method1,
method2: this. method2
})}
</div>
);
now I can not pass:
<Dialog
ref={(dialog)=>this.dialog=dialog}
method1={()=>console.log(1)}
method2 ={()=>console.log(1)}
>
<h4>somethign</h4>
</Dialog>
H4 needs to be a react component otherwise it will not set the props in cloneElement. How can I send simple HTML here, any help?
Detail about why your fiddle is not working as expected.
See the code here:
{this.props.show && React.cloneElement(this.props.children, {
contentStyle: {
color:'red'
}
})}
Issue is in case of Custom Component like CCC, contentStyle will get passed as props and you are using it like this:
style={this.props.contentStyle}
That means at the end style will be applied on div not contentStyle. But in case of div, contentStyle will get applied and that will not change anything because div expect style not contentStyle.
To solve your problem rename contentStyle to style at all the places.
Check this working fiddle.
The best link that can describe the answer is here:
https://reactjs.org/warnings/unknown-prop.html
The unknown-prop warning will fire if you attempt to render a DOM element with a prop that is not recognized by React as a legal DOM attribute/property. You should ensure that your DOM elements do not have spurious props floating around.
To fix it we should split the props before rendering. like:
render(){
const {children, addCustomProps, ...props} = this.props;
return(<div {...props}>{children}</div>);
}
To avoid the warning, we should pass only those props to the DOM , which can be recognized as a HTML attribute or React attribute like className.

React Native: onContentSizeChange event on TextInput element does not work on Android

I have a problem with TextInput event 'onContentSizeChange' on Android device.
Actually it is not been fired when I type message until the end of line and text goes to the next line the height of TextInput is not updated.
example:
return (
<TextInput
{...this.props}
multiline={Boolean(true)}
onChangeText={(text) => {
this.setState({text})
}}
onContentSizeChange={(event) => {
this.setState({height: event.nativeEvent.contentSize.height})
}}
style={[ additionalStyles, {height: this.state.height}, {fontSize: config.defaultFontSize} ]}
value={this.state.text}
underlineColorAndroid={'rgba(0,0,0,0)'}
/>
)
Does anybody know why it may happens?
P.S. Helped using onChange instead of onContentSizeChange
Please see React Native issue #11692. This looks like it will be fixed in an upcoming release. It's not clear, and it was only fixed a couple of weeks ago but maybe it will be in 0.46.
try onContentSizeChange
onContentSizeChange={e=>{
let inputH = Math.max(e.nativeEvent.contentSize.height, 35)
if(inputH>120) inputH =100
setIputHeight(inputH)
}}
onContentSizeChange does not return the size of the content, but on the container. It's still not fixed, which is also documented in an issue on the official react-native github repo

Correct way to handle conditional styling in React

I'm doing some React right now and I was wondering if there is a "correct" way to do conditional styling. In the tutorial they use
style={{
textDecoration: completed ? 'line-through' : 'none'
}}
I prefer not to use inline styling so I want to instead use a class to control conditional styling. How would one approach this in the React way of thinking? Or should I just use this inline styling way?
<div style={{ visibility: this.state.driverDetails.firstName != undefined? 'visible': 'hidden'}}></div>
Checkout the above code. That will do the trick.
If you prefer to use a class name, by all means use a class name.
className={completed ? 'text-strike' : null}
You may also find the classnames package helpful. With it, your code would look like this:
className={classNames({ 'text-strike': completed })}
There's no "correct" way to do conditional styling. Do whatever works best for you. For myself, I prefer to avoid inline styling and use classes in the manner just described.
POSTSCRIPT [06-AUG-2019]
Whilst it remains true that React is unopinionated about styling, these days I would recommend a CSS-in-JS solution; namely styled components or emotion. If you're new to React, stick to CSS classes or inline styles to begin with. But once you're comfortable with React I recommend adopting one of these libraries. I use them in every project.
If you need to conditionally apply inline styles (apply all or nothing) then this notation also works:
style={ someCondition ? { textAlign:'center', paddingTop: '50%'} : {}}
In case 'someCondition' not fulfilled then you pass empty object.
instead of this:
style={{
textDecoration: completed ? 'line-through' : 'none'
}}
you could try the following using short circuiting:
style={{
textDecoration: completed && 'line-through'
}}
https://codeburst.io/javascript-short-circuit-conditionals-bbc13ac3e9eb
key bit of information from the link:
Short circuiting means that in JavaScript when we are evaluating an AND expression (&&), if the first operand is false, JavaScript will short-circuit and not even look at the second operand.
It's worth noting that this would return false if the first operand is false, so might have to consider how this would affect your style.
The other solutions might be more best practice, but thought it would be worth sharing.
inline style handling
style={{backgroundColor: selected ? 'red':'green'}}
using Css
in js
className={`section ${selected && 'section_selected'}`}
in css
.section {
display: flex;
align-items: center;
}
.section_selected{
background-color: whitesmoke;
border-width: 3px !important;
}
same can be done with Js stylesheets
Another way, using inline style and the spread operator
style={{
...completed ? { textDecoration: completed } : {}
}}
That way be useful in some situations where you want to add a bunch of properties at the same time base on the condition.
First, I agree with you as a matter of style - I would also (and do also) conditionally apply classes rather than inline styles. But you can use the same technique:
<div className={{completed ? "completed" : ""}}></div>
For more complex sets of state, accumulate an array of classes and apply them:
var classes = [];
if (completed) classes.push("completed");
if (foo) classes.push("foo");
if (someComplicatedCondition) classes.push("bar");
return <div className={{classes.join(" ")}}></div>;
If you want assign styles based on condition, its better you use a class name for styles. For this assignment, there are different ways. These are two of them.
1.
<div className={`another-class ${condition ? 'active' : ''}`} />
<div className={`another-class ${condition && 'active'}`} />
style={{
whiteSpace: "unset",
wordBreak: "break-all",
backgroundColor: one.read == false && "#e1f4f3",
borderBottom:'0.8px solid #fefefe'
}}
I came across this question while trying to answer the same question. McCrohan's approach with the classes array & join is solid.
Through my experience, I have been working with a lot of legacy ruby code that is being converted to React and as we build the component(s) up I find myself reaching out for both existing css classes and inline styles.
example snippet inside a component:
// if failed, progress bar is red, otherwise green
<div
className={`progress-bar ${failed ? 'failed' : ''}`}
style={{ width: this.getPercentage() }}
/>
Again, I find myself reaching out to legacy css code, "packaging" it with the component and moving on.
So, I really feel that it is a bit in the air as to what is "best" as that label will vary greatly depending on your project.
Sorted way to apply inline styling on some condition.
style={areFieldsDisabled ? {opacity: 0.5} : '' }
If you do not want to overwrite the initial style, you can use empty styling with {}. For instance, assigning a background-color, when you need to keep the initial color if the condition is not met.
style={ onError ? {backgroundColor: 'red'} : {} }
style={ completed ? {textDecoration: 'line-through'} : {} }
The best way to handle styling is by using classes with set of css properties.
example:
<Component className={this.getColor()} />
getColor() {
let class = "badge m2";
class += this.state.count===0 ? "warning" : danger;
return class;
}
You can use somthing like this.
render () {
var btnClass = 'btn';
if (this.state.isPressed) btnClass += ' btn-pressed';
else if (this.state.isHovered) btnClass += ' btn-over';
return <button className={btnClass}>{this.props.label}</button>;
}
Or else, you can use classnames NPM package to make dynamic and conditional className props simpler to work with (especially more so than conditional string manipulation).
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
In case someone uses Typescript (which does not except null values for style) and wants to use react styling, I would suggest this hack:
<p
style={choiceStyle ? styles.choiceIsMade : styles.none}>
{question}
</p>
const styles = {
choiceIsMade: {...},
none: {}
}
Change Inline CSS Conditionally Based on Component State.
This is also the Correct way to handle conditional styling in React.
condition ? expressionIfTrue : expressionIfFalse;
example =>
{this.state.input.length > 15 ? inputStyle={border: '3px solid red'}: inputStyle }
This code means that if the character is more than 15 entered in the input field, then our input field's border will be red and the length of the border will be 3px.

Categories

Resources