How to Pass in Store as a prop - reactjs

I am currently having a problem getting store to be passed in as a prop and am wondering what to label a few things.
The current error is within create store, I'm unsure what to do with it.
I have tried other methods and only want to use the store method where I pass it in as a prop
import React from 'react';
import { MockGit } from './Constants';
import ExpansionPanelSummary from '#material-ui/core/ExpansionPanelSummary';
import ExpansionPanelDetails from '#material-ui/core/ExpansionPanelDetails';
import Typography from '#material-ui/core/Typography';
import ExpandMoreIcon from '#material-ui/icons/ExpandMore';
import ExpansionPanel from '#material-ui/core/ExpansionPanel';
import Button from '#material-ui/core/Button';
import TestAPI from './TestAPI';
import { displayGitData, userInfoURL, getDataSaga } from '../sagas/sagas';
import { createStore } from 'redux';
class GitData extends React.Component {
constructor(props) {
super(props);
}
render() {
const store = createStore(...); //this is what im unsure of.
const { store } = this.props;
return (
<ExpansionPanel>
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}>
<Typography> {MockGit} </Typography>
</ExpansionPanelSummary>
<ExpansionPanelDetails>
{displayGitData()}
{userInfoURL()}
{getDataSaga()}
<TestAPI />
</ExpansionPanelDetails>
</ExpansionPanel>
);
}
}
export default GitData;
The goal is to get store passed in as a prop with no errors.
Any help would be great, Thanks!

You're doing it wrong, here's the recommended way to use React with Redux:
store.js
import { createStore } from 'redux';
export default createStore(...)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store.js'
const App = () => (<h1>Hello from App</h1>);
ReactDOM.render(
<Provider store={store}><App/></Provider>
document.querySelector('#react-root')
);
You now have an app that is bound with the store.
The react-redux npm package allows also to bind component props to store dispatches and store state, example:
my-component.js
import React from 'react';
import { connect } from 'react-redux';
class MyComponent extends React.Component {
render() {
return (
<p>{this.props.hello}</p>
)
}
}
export default connect(state => ({hello: state.helloReducer.value}))(MyComponent)
For further tutorials, check the official docs of react-redux, or this good youtube playlist.

Related

how can i use react redux in class component?

im a new to redux, and i want to know if it possible to use redux in class component.
we know that hooks works only in function component, so i export a function to use useSelector to access the store :
import { useSelector, useDispatch } from "react-redux";
export default function Selector() {
const counter = useSelector((state) => state.counter);
return counter;
}
and import it to the compone component so will be like this:
import React, { Component } from "react";
import selector from "../Store/selector";
export class Compone extends Component {
componentDidMount() {
console.log(selector());
}
render() {
return (
<>
<h1>
Counter: <span>0</span>
</h1>
<button style={{ marginRight: "10px" }}>Increase</button>
<button>Decrease</button>
</>
);
}
}
export default Compone;
and i import compone component to the App root component:
import React, { Component } from "react";
import Compone from "../components/compone/Compone";
export class App extends Component {
render() {
return (
<div>
<Compone />
</div>
);
}
}
export default App;
so this didn't work for me, is there a way to use redux in class component?,
how to use redux in class component,
how to use react redux in class component,
First of all you have to create some actions and some reducers.
Then you need to create a store using the reducers.
After that you can use connect method of react-redux with your class component.

Getting undefined when accessing redux stores state property in react App

I am using redux in my react app and I am getting undefined when I access redux state property in one of my component, why is that? the state is valid when I call console.log in reducer file : here is my reducerFile :
const initState = {
isCurrentUser : true
}
export default function(state=initState, action) {
console.log(`this is from localAuthReducer ${state.isCurrentUser}`)
switch(action.type) {
default:
return state
}
}
Here is my react component :
import React, {Component} from 'react';
import styles from './IndexPage.module.scss';
import { connect } from 'react-redux';
import Header from './../../components/Header/Header';
class IndexPage extends Component {
render() {
return(
<div className={styles.container}>
<Header
isCurrentUser = {this.props.isCurrentUser}
/>
{ console.log(`this is from indexPage ${this.props.isCurrentUser}`)}
</div>
);
}
}
function mapStateToProps(state) {
return {
isCurrentUser : state.isCurrentUser
}
}
export default connect(mapStateToProps, null)(IndexPage);
Here is my index.js file :
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App/App';
import {Provider } from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import reducers from './reducers/index';
import reduxThunk from 'redux-thunk';
const store = createStore(
reducers,
applyMiddleware(reduxThunk)
);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>
, document.querySelector("#root"));
I dont know where I am going wrong isCurrentUser must have value of true as it is the default value of the redux state

Children component gets props as undefined

I'm trying to pass props to my children components which are under the controller. I'm using redux and react-router for navigation. The problem is that everything is fine in the controller, it gets its initial props, but when I'm passing them to a child I have an undefined either the constructor or in render function. Here is my code:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import moment from 'moment'
import LawsuitSchedule from '../components/LawsuitSchedule'
import LawsuitCalendar from '../components/LawsuitCalendar'
class LawsuitScheduleContainer extends Component {
constructor (props) {
super(props)
}
render () {
let {schedule} = this.props
console.log(schedule)
return (
<LawsuitCalendar initialDate={schedule.initialDate}
selectedDate={schedule.selectedDate}
scheduledDates={schedule.scheduledDates}/>,
<LawsuitSchedule/>
)
}
}
const mapStateToProps = state => ({
schedule: state.schedule,
})
export default connect(mapStateToProps)(LawsuitScheduleContainer)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import momentPropTypes from 'react-moment-proptypes'
import moment from 'moment'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import '../styles/lawsuitCalendar.css'
export default class LawsuitCalendar extends Component {
constructor (props) {
super(props)
console.log(props)
}
propTypes = {
selectedDate: momentPropTypes.momentString,
scheduledDates: PropTypes.array.isRequired,
}
handleChange = (date) => {
this.setState({
selectedDate: date,
})
}
render () {
let {selectedDate, scheduledDates} = this.props
let highlightWithRanges = [
{
'scheduled-date': scheduledDates,
},
]
return (
<DatePicker
inline
selected={selectedDate}
onChange={this.handleChange}
highlightDates={highlightWithRanges}
/>
)
}
}
The problem was in another component, which renders LawsuitCalendar too. I have no clue why it was displayed only once, but I have solved my problem with props -- I just didn't pass them. I've added it, maybe someone can answer why has that happened?
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Grid, Row, Col } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import ReactTable from 'react-table'
import matchSorter from 'match-sorter'
import LawsuitCalendar from '../components/LawsuitCalendar'
import '../styles/lawsuitGrid.css'
import data from '../utils/data.json'
export default class LawsuitSchedule extends Component {
render () {
return (
<Grid>
<Row className="show-grid">
<Col md={4}><LawsuitCalendar/></Col>
<Col md={8}>
<ReactTable data={data}
...
/>
</Col>
</Row>
</Grid>
)
}
}

MuiThemeProvider: How to use different themes for different routes?

I need to slightly change the theme depending on the current section of the site.
It seems that MuiThemeProvider only sets muiTheme on load; but it needs to be updated when the props change.
How can this be done?
You can try to put the theme in a wrapping component that keeps the theme in it's state. Using React's context this component exposes a function to child components to change the state.
import React, { Component } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import PropTypes from 'prop-types';
import theme from './theme';
import themeOther from './theme-other'
class Wrapper extends Component {
static childContextTypes = {
changeTheme: PropTypes.func
};
constructor(props) {
super(props);
this.state = {
muiTheme: getMuiTheme(theme)
};
}
getChildContext() {
return {changeTheme: this.changeTheme};
}
changeTheme = () => {
this.setState({
muiTheme: getMuiTheme(themeOther)
})
};
render() {
return (
<MuiThemeProvider muiTheme={this.state.muiTheme}>
{this.props.children}
</MuiThemeProvider>
)
}
}
export default Wrapper;
In some child component you can access the context and call the changeTheme function to set a different theme in the state. Make sure to include contextTypes else you can't access the function.
import React, { Component } from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import PropTypes from 'prop-types'
class ChildComponent extends Component {
static contextTypes = {
changeTheme: PropTypes.func
};
render() {
return (
<RaisedButton
primary
onTouchTap={this.context.changeTheme}
label="Change The Theme"
/>
);
}
}
export default ChildComponent;
In the root of your app just render the wrapper.
ReactDOM.render(
<Wrapper>
<App />
</Wrapper>,
document.getElementById('root')
);
EDIT:
My first solution might have been abit too much. Since you are replacing the whole theme for the whole app. You can also use the MuiThemeProvider down the tree like so.
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import inject from 'react-tap-event-plugin';
inject();
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import theme from './theme';
ReactDOM.render(
<MuiThemeProvider muiTheme={getMuiTheme(theme)}>
<App />
</MuiThemeProvider>,
document.getElementById('root')
);
In a child component you can just use the MuiThemeProvider again and override some properties. Note that these changes will reflect on all the children inside this MuiThemeProvider.
import React, { Component } from 'react';
import RaisedButton from 'material-ui/RaisedButton';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import theme from './theme';
import { green800, green900 } from 'material-ui/styles/colors';
const localTheme = getMuiTheme(Object.assign({}, theme, {
palette: {
primary1Color: green800,
primary2Color: green900
}
}));
class App extends Component {
render() {
return (
<div>
<RaisedButton
primary
label="Click"
/>
<MuiThemeProvider muiTheme={localTheme}>
<RaisedButton
primary
label="This button is now green"
/>
</MuiThemeProvider>
</div>
);
}
}
export default App;

reactjs mobx without decorators not working

I am trying to incorporate mobx with react. Since I spawned my application using create-react-app, I can't use decorators given by mobx.
Given that we can use mobx without decorators as per this documentation: https://mobxjs.github.io/mobx/best/decorators.html
Here's a component that I created:
import React, { Component } from 'react';
import observer from 'mobx-react';
export const TestComponent = observer(class TestComponent extends Component {
render() {
return <div>Just a test component!</div>
}
});
Here's a simple calling of the above component:
import React, { Component } from 'react';
import './App.css';
import Auth from './Auth'
import { TestComponent } from './Test'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import authStore from './stores/Store'
class App extends Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
return (
<div className="app">
<MuiThemeProvider>
<div>
<TestComponent store={authStore} />
</div>
</MuiThemeProvider>
</div>
);
}
}
export default App;
Now when I run the above component, I get error: Uncaught TypeError: (0 , _mobxReact2.default) is not a function(…) nothing get displays in console.
What am I doing wrong here?
Please use import {observer} from 'mobx-react';
N.B. note that decorators can be used with create-react-app by using custom-react-scripts, as explained here)

Resources