Container and Component of the same Class - reactjs

I'm new to React and Redux,
I'm trying to use a Class as a Redux Container (so the state is managed by reducer) and also a classic Component with another instance (no link to reducer)
So basically something like this:
class BaseLogo extends Component {
constructor(props){
super(props);
}
render(){
let link = this.props.linkLogo || this.props.link;
return (
<Link className="btn btn-primary" to={link}>
{this.props.logoName}
</Link>
);
}
}
function mapStateToProps(state){
return {
linkLogo: state.linkLogo
};
}
let Logo = connect(mapStateToProps)(BaseLogo);
export {Logo, BaseLogo as Button};
So I wanna use Logo as a Container, and Button as a Component (no reducer) with a specified props.
But as the way Redux bind it, whenever I create an instance of class Logo, there will be a reducer.
Is there somehow I can isolate the connect()() from the class itself ?
Thank you.

I found the error, it dues to a bad implementation in the code. Thank you all

Related

How to change the style of a reactjs component by code

I need to change the style of some child components of a react components. Something like this:
import React, { Component } from 'react';
class Parent extends Component {
onClickHandler = (event) => {
this.props.children[0].props.style.marginLeft = "-100%";
}
render() {
<div onClick={this.onClickHandler}>
{this.props.children}
</div>
}
}
export default Parent;
The error i'm getting is:
TypeError: Cannot add property marginLeft, object is not extensible
May you help me guys?
Thanks a lot !!
The error you are getting is because you cannot modify props, since those are immutable. A simpler approach can be done using plain CSS and simple state management.
With this technique, you need a state variable to know when to add the class modifier. That class modifier is in charge of overriding the styles of the child component.
The JS would look like this:
import React, { Component } from "react";
class Parent extends Component {
constructor() {
this.state = {
bigMargin: false
};
}
onClickHandler = (event) => {
event.preventDefault();
this.setState({ bigMargin: true });
};
render() {
return (
<div className={`parent-class ${bigMargin && 'big-margin'}`} onClick={this.onClickHandler}>
{this.props.children}
</div>
);
}
}
export default Parent;
And the CSS can be something as simple as this (or as complex as you may want)
.big-margin:first-child {
margin-left: -100%;
}
React props are immutable and you can't change them, they are read only and you can't add new properties.
This is done via Object.preventExtensions, Object.seal and Object.freeze.
To "fix" the error partialy you should define marginLeft in the first child of your Parent component
<Parent>
<p style={{marginLeft: '0'}}>1</p>
<p>2</p>
</Parent>
You will get now a new Error :
TypeError: "marginLeft" is read-only
Imagine having the ability to change props, and you pass the same prop to many children, one of them change it value, this will lead to unexpected behavior.
Try something like
Grab the element by its id on click
document.getElementById("demo").style.marginLeft = '-100px'
Or use react refs to grab the element

Passing React Navigation to Child of Child Component

I'm dynamically building my "screen" with the use of child "row" and "button" components. I'm only using this method because I can't find a flex-flow property available for react-native.
So basically I'm mapping through an array of arrays to build each row, and within the row, mapping through each array to build each button. Because the onPress needs to be set in the button, I'm passing the URL for each
onPress{() => this.props.navigation.navigate({navigationURL})
as a prop, first to the row, and then to the button. The problem is I keep getting the error 'Cannot read property 'navigation' of undefined. I'm sure this is because only the actual "screens" within the navigator have access to the navigation props. I've also tried passing
navigation={this.props.navigation}
but had no success. I've looked through all of the documentation and can't seem to find anything helpful. Anyone else encountered a similar situation?
If you want to access the navigation object from a component which is not part of navigator, then wrap that component in withNavigation HOC. Within the wrapped component you can access navigation using this.props.navigation. Take a look at the official document
Sample
import { withNavigation } from 'react-navigation';
...
class CustomButton extends React.Component {
render() {
return <Button title="Back" onPress={() => {
this.props.navigation.goBack() }} />;
}
}
export default withNavigation(CustomButton);
Hope this will help!
Ahhh, silly mistake. I wasn't setting up Props in the constructor. Thank you Prasun Pal for the help! Here's my code if someone else has an issue.
import React, { Component } from 'react'
import { Image, Text, TouchableOpacity, View } from 'react-native'
import { withNavigation } from 'react-navigation'
class ButtonName extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<TouchableOpacity
onPress={() => this.props.navigation.navigate('PageName')}
>
</TouchableOpacity>
)
}
}
export default withNavigation(ButtonName);

React. how to pass props from onClick to function

I am new to React, I am trying to create an app in which I can click on a button and a function will run countdown timer, but If I pass props from onClick to begin function like this, onClick={begin(props.subject)} the function will run before I click. and if I use onClick with begin without argument, there is no props being passed down. how can I fix that? thanks
import React from 'react';
import SubjectForm from './SubjectForm';
const EditSubject=(props)=>{
return(
<div>
<button onClick={begin}>start</button>
</div>)
};
const begin = (props)=> {
console.log(props.subject)
}
const mapStateToProps=()=>{};
export default connect(mapStateToProps)(EditSubject);
also, is there a way or trick to use a variable inside of begin function from an outside function? so I can make a pause button to pause seInterval in begin function.
You are using functional (stateless) components in this example. You can also use ES6 classes to represent React components, with functions being methods of the class. Then you may make functions like begin in your code as class methods, so they can access class data members like props.
See the code below:
import React from 'react';
import SubjectForm from './SubjectForm';
class EditSubject extends React.Component {
constructor() {
super();
this.begin = this.begin.bind(this);
}
begin() {
console.log(this.props.subject);
}
render() {
return (
<div>
<button onClick={begin}>start</button>
</div>
);
}
};
const mapStateToProps=()=>{};
export default connect(mapStateToProps)(EditSubject);
This is just a best practice if your component has states, and methods. Using functional components like in your example, you may use simply the following:
const EditSubject = (props) => {
return (
<div>
<button
onClick={() => begin(props)} // using props here
>
start
</button>
</div>
);
};
Simple, right ?

Redux: Where to place "dumb" handlers?

Let's say I have a component with a click handler that doesn't need to modify the Redux store. i.e. it might, depending on the props of the component, initiate a download of a file.
i.e. you have an web interface for a list of videos that are processing on the server. Click on a video item checks the props to see if the video has finished processing. If it has, it'll start downloading the video, other it'll pop up an alert explaining that the video is still processing.
Usually, handlers tend to be defined in mapDispatchToProps. However, in this case, I don't actually need to touch the state, so defining the handler in there doesn't feel correct.
Would the correct place for such a handler be in the 'dumb' component rather than the 'smart' container?
I would still have this in the container and pass the function down as a prop -- just not in mapDispatchToProps.
e.g:
// SmartComponent.js
import React, { Component } from 'react'
import DumbComponent from '/path/to/DumbComponent'
export class SmartComponent extends React.Component {
constructor(props) {
super(props);
this.handleOnClick = this.handleOnClick.bind(this);
}
handleOnClick(params) {
// do whatever you need to do here
}
render() {
return (
<DumbComponent handleOnClick={this.handleOnClick} />
);
}
};
export default SmartComponent;
// DumbComponent.js
import React from 'react'
import Button from '/path/to/button'
export const DumbComponent = (props) = {
const { handleOnClick } = props;
return (
<Button onClick={handleOnClick} />
);
}
export default DumbComponent;
I should probably also add that I usually structure it so that I have another level above this which is connected to the store - something like ContainerComponent for example - which is usually the view for the route. This is why I have not connected this SmartComponent to the store. You could do that though.

How to extend a React component?

Let's say there's a React component that I like, but want to modify. For this example, we'll use Material UI's LinearProgress. I want to make a clickable seek bar out of it.
class SeekBar extends LinearProgress {
componentDidMount() {
super.componentDidMount();
console.log('my stuff here');
}
}
But I feel like I might be very limited as to what I can do as far as changing what render returns. Maybe I'm going about this all wrong, though. If I like a particular React component such as a Material UI component, what is a good, reusable way to customize its look and functionality and make it my own?
In the ES6/JSX/React world, you can extend component behaviors and values in many ways. I'd recommend one of the following, considering that you use Material UI.
First case:
You have two components that extend the Component from React:
class ExampleComponent extends React.Component {
render () {
return(
<div>
<button {...this.props}>
Click me!
</button>
</div>
)
}
}
class RenderComponent extends React.Component {
clickHandler () {
console.log('Click fired!')
}
render () {
return(
<ExampleComponent onClick={this.clickHandler.bind(this)} />
)
}
}
In that example, onClick is passed via props inside the rendered ExampleComponent. Example here.
Second case:
This is similar on how Material UI extends their own components:
class ExampleComponent extends React.Component {
clickHandler () {
console.log('Click fired!')
}
}
class RenderComponent extends ExampleComponent {
render () {
return(
<div>
<button onClick={this.clickHandler.bind(this)}>
Click me!
</button>
</div>
)
}
}
In this example, you have one component that extends Component from React but only has event methods. Then, you extend this component and render your own with the extended behavior. Here is a live example.
Hope it helps!
One way is:
export default class Seekbar extends React.Component{
// perform any modification
render(){
return <LinearProgress ...changes/>
}
}
Another way is a Higher Order Component, HOC. Here's a great blog with more info: http://natpryce.com/articles/000814.html
I think with Material-UI your best bet would be to wrap it and make any modifications you'd like. Unfortunately this project is very tightly coupled thanks to things like inline styles and their thememanager so taking a single component out may be difficult. HOC would be better for things like sharing some smart functionality across components, like passing a "theme" prop automatically to components.

Resources