React native should I pass props or use Redux - reactjs

So I have a router component which sits at the top of the screen in my app. There is a menu button in this component which is visible when certain other pages/components are loaded.
When this menu button is clicked, I need to communicate this to the component which is currently displaying the page so that it can display a context menu.
The context menu and the menu button both work independently. However, I'm confused at how to wire it up. How do I efficiently communicate a true/false toggle between those two components? I thought I could do it with props but then I feel that you cannot update the props after they've been passed. This leads me to think I may need to have a store implemented which both components can read/write from/to. This way the router component will update the store on each menu button click, and the other component could have its state updated based on the store's state which I could use to toggle the menu visible/hidden.
Does that make sense and if so what's the best way of tackling it?
Router code: - Parent, menu() fires when clicking the Menu button
const RouterRecipeComponent = () => {
function menu() {
console.log('clicky');
}
const MenuIcon =
(<TouchableOpacity
onPress={() => menu()}
style={{ backgroundColor: 'red', width: 30, height: 30 }}
>
<Text>MENU</Text>
</TouchableOpacity>);
return (
<Router
sceneStyle={styles.sceneStyleWithSettings}
navigationBarStyle={styles.navBar}
titleStyle={styles.navBarTitle}
barButtonIconStyle={styles.barButtonIconStyle}
>
<Scene
key="Recipes"
component={Recipes}
title={content.recipe_heading}
rightTitle="Menu" initial
renderRightButton={() => MenuIcon}
/>
Recipes code - Displays a bunch of stuff including the settings panel (code included) which will be toggled visible/hidden on each click of the menu button in the above Router code. So my thoughts are to be able to toggle the state settingsPanel true/false to display the below:
renderSettingsPanel() {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
if (this.state.settingsPanel === true) {
return (
<View style={styles.settingsPanel}>
{this.theSettings()}
</View>
);
}
return (
<View style={[styles.settingsPanel, { top: -80, position: 'absolute', opacity: 10 }]}>
{this.theSettings()}
</View>
);
}

Related

Is it possible to use the touch ripple effect of MUI on a div?

I have read different answers of similar questions, but they are all old and don't seem to work in the latest version of MUI.
I need to apply the touch ripple effect on a div, but I can't use a button or a ButtonBase element because there is another button inside it.
Thanks in advance for the reply.
Yes, you can use TouchRipple to emulate the ripple effect. This component is undocumented, but you can see how it's used in the ButtonBase and learn to use it yourself.
First, you need to pass a ref to TouchRipple and call ref.current.start(e) or ref.current.stop(e) when you want to start or stop the effect respectively.
e is the event object. When you call start(e), it needs the mouse or touch position (from mousedown or touchstart event) to know where to start the ripple effect (Source). You can override this behavior by setting center props to true, which makes the ripple effect always start at the middle.
Below is the minimum working example to get you started:
function App() {
const rippleRef = React.useRef(null);
const onRippleStart = (e) => {
rippleRef.current.start(e);
};
const onRippleStop = (e) => {
rippleRef.current.stop(e);
};
return (
<div
onMouseDown={onRippleStart}
onMouseUp={onRippleStop}
style={{
display: "inline-block",
padding: 8,
position: "relative",
border: "black solid 1px"
}}
>
Button
<TouchRipple ref={rippleRef} center={false} />
</div>
);
}
Live Demo
You Can Use ButtonBase API
With ButtonBase API you can pass component prop as div or any component you want
For Eg.
import { ButtonBase, Typography } from "#mui/material";
const App = () => {
return (
<ButtonBase component="div">
<Typography fontSize="1.2rem">Hello, I'm a div with MUI Ripple Effect!</Typography>
</ButtonBase>
)
}
export default App;

How to Change Title Attribute in React Native Button Component

I have a few React components that look something like this within an app:
<View style={{margin: 5}}>
<Button title='Enable Headlights' color='#00759A' onClick={doChanges}/>
</View>
I want the Button component to change its color and text whenever its clicked. I was planning on having the function doChanges do this, but I can't figure out a way to modify the title and color attributes. I've seen custom made components that make these kinds of changes in state by calling setState within the component, but Button isn't a component that I made. I tried doing something along the lines of:
var text = "Enable headlights"
function doChanges(text) {
text = "Disable headlights"
}
<View style={{margin: 5}}>
<Button title={text} color='#00759A' onClick={()=> {doChanges(text)}}/>
</View>
But that doesn't seem to work the way I want it to. I think it's because even though the variable text is changing, the actual component isn't rerendering, so the changes in text never actually appear.
There doesn't seem to be a way to force the component to rerender, and I don't see how there's a way I can modify the title and color attributes of the Button component.
Do I have to make a custom component that's subclassed from Button in order to get the functionality I want? Or is there a specific way for how I'm supposed to go about doing something like this in React?
Any help would be appreciated!
If you are supposed to make changes at the UI level then you should use the state to render the updated view.
like:
If you are using Class Component:
class Demo extends Component {
constructor(props) {
super(props)
this.state = {
buttonText: "Enable headlights"
}
this.doChanges = this.doChanges.bind(this);
}
function doChanges(text) {
this.setState({ buttonText: "Disable headlights" });
}
render() {
return (
<View style={{margin: 5}}>
<Button title={this.state.} color='#00759A' onClick={()=> {doChanges(text)}}/>
</View>
)
}
}
If you are using Functional Component:
const Demo = props => {
const [buttonText, setButtonText] = useState("Enable headlights")
function doChanges(text) {
setButtonText("Disable headlights");
}
return (
<View style={{margin: 5}}>
<Button title={text} color='#00759A' onClick={()=> {doChanges(text)}}/>
</View>
)
}
check out more about the state:
https://reactjs.org/docs/state-and-lifecycle.html

How Can I make my React Button Component updates CSS only on the specific page?

So I created this button component using the following code
const STYLES = ['btn--primary', 'btn--outline', 'btn--test'];
const SIZES = ['btn--medium', 'btn--large'];
const DISPLAY = ['btn--show', 'btn--hidden'];
export const Button = ({
children,
type,
onClick,
buttonStyle,
buttonSize,
buttonDisplay
}) => {
const checkButtonStyle = STYLES.includes(buttonStyle)
? buttonStyle
: STYLES[0];
const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0];
const checkButtonDisplay = DISPLAY.includes(buttonDisplay)
? buttonDisplay
: DISPLAY[0];
return (
<Link to='/sign-up'>
<button
className={`btn ${checkButtonStyle} ${checkButtonSize} ${checkButtonDisplay}`}
onClick={onClick}
type={type}
>
{children}
</button>
</Link>
);
So I have this button component inside of my navbar component and I also have it inside of my home page section component.
My issue is that whenever I shrink the page to mobile, I want to make the button component in the navbar to display: none and then on the home section I want it to show
What ends up happening is that since it's a component, any CSS style I add to it will go on any other page that is using the component, so basically my button disappears on the home page section when I need it to display
I tried to add an Id to the button component, but that didn't work
<Button id='nav-btn' buttonStyle='btn--outline'>
SIGN UP
</Button>
and I don't know how I'd add a custom class or id to the navbar button without it applying to all the other button components on my homepage
Hide it with an expression, e.g., { showButton && <Button /> }. If showButton is true, you'll see the button, if not, you won't.
If you want to do it via CSS, use a media-query to set display: none on whatever screen size it's supposed to disappear on.
Edit in response to the comment
#media (max-height: 960px) {
display: none;
}
That reads, "If the height is less than 960px, set this property."
If you want a "special" button that hides on a screen size, create a higher-order component that wraps your button.
const NinjaButton => () => {
// do stuff
return <Button cssOverrideProp={cssWithMediaQueryThatHides} />
}
In Button, you can conditionally apply that css,
className=`{/* your other css */ ${cssOverrideProp || ''}}`
Then you can use that button anywhere it's supposed to hide.

React disable and enable button based on parent input function and click of button

So basically i have a parent component which uses a child button component. Basically currently when the input validation is not correct it will keep the button disabled. However now I have tried to disable the button on click. The button is currently a pure component and i started to use hooks but not sure how i can still get the validation running.
Code is below
<ChildButton
onClick={() => {
this.checkSomething= this.checkCreds();
}}
enabled={this.validateInput()}
/>
My pure component currently looks like this:
export function AButton({ onClick, enabled, text }) {
const [disabled, setDisabled] = useState(!enabled);
function handleClick() {
setDisabled(!disabled);
//onClick();
}
return (
<Button
style={{ display: "block", margin: "auto" }}
id="next-button"
onClick={handleClick}
disabled={disabled}
>
{text}
</Button>
);
}
So i can get the disable button to work in both scenairos. As the enabled is always being passed down into this pure component so need to keep setting state of it.
I ended up using useEffect from react hooks
useEffect(() => setDisabled(!enabled), [enabled]);
This will check every time the enabled props is updated from the parent. Similar to how componentDidUpdate would work

Why isn't my prop logging or being passed in React Native?

I made a component called IconButton that takes some props and passes any additional props through.
import Icon from 'react-native-vector-icons/FontAwesome';
const IconButton = ({ icon, title, ...props }) => {
console.log(props); // Actual: {}, expected: { onPress: [function] }
return (
<View style={ iconBox } { ...props }>
<Icon name={ icon } size={ 48 } color="black" />
<Text>{ title }</Text>
</View>
};
Then I rendered it:
const render = () => (
<IconButton icon='plus' title='add' onPress={ () => console.log('hi') } />
);
However when I tried to log it with console.log, onPress did not show up; it logged an empty object. Also, it wasn't passed to my View because it wasn't calling onPress when pressed. But when I pass different props with different types such as numbers and strings, it shows up fine.
Why isn't it being passed to my View and why isn't the prop being logged? I'm also using Expo if that may affect anything. I've set up an issue on GitHub.
The logging issue is a bug with Expo, which uses JSON.stringify and other methods to give an output, but isn't outputting objects correctly. The bug also encompasses functions such as onPress here which are part of objects, and causes console.log to not log it at all, seen here. The issue is on GitHub and is set to be fixed in the next SDK update on June 19, 2017.
Now onto a different issue,View doesn't take an onPress prop, it's not supposed to be touchable. To have a touchable view, try the following wrappers:
TouchableHighlight, on touch, there's a tint added to the view
TouchableNativeFeedback, Android only, regular view that responds to touches
TouchableOpacity, on touch, the view opacity is decreased
TouchableWithoutFeedback, on touch there's no visible feedback but accepts taps (you shouldn't use this, all interactions should have visible feedback for a good UX)

Resources