React REDUX not updating the state to the new one - reactjs

Just trying to build a simple react-redux code here. Whenever I click one of the button with some data value attached to it, I just want it to use it to update state of my react app.
The directory composition is :
src/index.js
src/App.js
src/reduxButtonGroup.js
src/reduxActions.js
src/reducers/index.js
src/reduxStore.js
src/reduxHelloWorld.js
Now, coming to the codes here is how App.js looks like:
import React from 'react';
import HelloWorld from './reduxHelloWorld.js';
import {store} from './reduxStore.js'
import ButtonGroup from './reduxButtonGroup.js';
import 'bootstrap/dist/css/bootstrap.min.css';
class App extends React.Component {
render(){
return(
<React.Fragment>
<HelloWorld name = {store.getState().name} />
<ButtonGroup names = {["NameA","NameB","NameC"]}/>
</React.Fragment>
)
}
}
export default App;
Here is how reduxButtonGroup.js looks like:
import React from 'react';
import Button from 'react-bootstrap/Button';
import {store} from './reduxStore.js';
import {setName} from './reduxActions.js';
const ButtonGroup = ( {names} ) => (
<div>
{names.map((name,i) => (
<Button data-name={name} key={`btn-${i}`} style={{marginRight: "15px"}} className={"btn btn-danger"} onClick={dispatchBtnAction}>
{name}
</Button>
))}
</div>
);
function dispatchBtnAction(e){
const name = e.target.dataset.name;
console.log(name);
store.dispatch(setName(name));
}
export default ButtonGroup;
And reduxActions.js:
export function setName (name) {
return {
type: "SET_NAME",
name: name
}
}
Also, reducers/index.js:
export default (state,action) => {
console.log(action.name)
switch(action.type){
case "SET_NAME":
console.log("here")
return{
...state,
name: action.name
};
default:
return state;
}
};
Here is how reduxStore.js looks like:
import {createStore} from 'redux';
import reducer from "./reducers";
const initialState = { name: "initialName " };
export const store = createStore(reducer, initialState);
And at last reduxHelloWorld.js:
import React from 'react';
class HelloWorld extends React.Component{
render(){
return(
<React.Fragment>
<h1>Hello {this.props.name}</h1>
</React.Fragment>
)
}
}
export default HelloWorld;
Now, in the terminal I can see the right values in action.type and action.name . However I think that somehow the part shown below is not working. i.e., I'm unable to update my state variable called name to action.name .
return{
...state,
name: action.name
};
Though I'm getting the right values, my component is not getting rendered with the right values. Any idea what I'm doing wrong over here. Any help would be highly appreciated.

Related

default is not a function React Type error

Hi guys i want to make speech to text in React component. But when i run it I get this error:
react_speech_recognition__WEBPACK_IMPORTED_MODULE_1___default(...) is not a function
Can someone show me what to do?
import React, { Component } from 'react'
import SpeechRecognition from 'react-speech-recognition'
class Mic extends Component {
render() {
const { transcript, resetTranscript, browserSupportsSpeechRecognition } = this.props
if (!browserSupportsSpeechRecognition) {
return null
}
return (
<div>
<button onClick={SpeechRecognition.startListening}>Start</button>
<button onClick={SpeechRecognition.stopListening}>Stop</button>
<button onClick={resetTranscript}>Reset</button>
<p>{transcript}</p>
</div>
)
}
}
export default SpeechRecognition(Mic)
In app.js i run it like this (if this is necessary):
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Container from './components/container/Container';
import Database from './components/database/Database';
import Mic from './components/mic/Mic';
import Test from './components/test/Test';
function App() {
return (
<Mic/>
//<Test/>
);
}
export default App;
It is because of this line SpeechRecognition(Mic) . The Error states that the default export from your module is not a function which means that SpeechRecognition is not a function so you cannot call it .
change your code as
import React from 'react'
import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition'
const Mic = () => {
const { transcript, resetTranscript } = useSpeechRecognition()
if (!SpeechRecognition.browserSupportsSpeechRecognition()) {
return null
}
return (
<div>
<button onClick={SpeechRecognition.startListening}>Start</button>
<button onClick={SpeechRecognition.stopListening}>Stop</button>
<button onClick={resetTranscript}>Reset</button>
<p>{transcript}</p>
</div>
)
}
export default Mic
Looks like you have installed the latest version, but trying to use it in old way.
Please take a look at this Migration Guide

Get ref from connected redux component withStyles

I have this export of a working component:
export default connect(
mapStateToProps, actions,
null, { withRef: true, forwardRef: true }
)(withTheme()(withStyles(styles)(MainMenu)));
And its call:
<MainMenu
ref={(connectedMenu) => this.menuRef = connectedMenu.getWrappedInstance()}
user={user}
/>
I've expected to get a MainMenu ref, but I keep getting WithTheme object instead.
I've also tried to get through innerRef, but got the following errors:
TypeError: connectedMenu.getWrappedInstance is not a function
TypeError: Cannot read property 'getWrappedInstance' of null
Before all of that I've tried that React.createRef() format, but it didn't worked.
How do I get this ref?
Assuming you are using v4 of Material-UI, your syntax for withTheme is incorrect. In v4 the first set of parentheses was removed.
Instead of
withTheme()(YourComponent)
you should have
withTheme(YourComponent)
Below is code from a modified version of the react-redux todo list tutorial that shows the correct syntax. I've included here the two files that I changed (TodoList.js and TodoApp.js), but the sandbox is a fully working example.
In TodoApp, I use the ref on TodoList to get and display its height. The displayed height will only get updated if TodoApp re-renders, so I've included a button to trigger a re-render. If you add a couple todos to the todo list, and then click the re-render button, you will see that the new height of the list is displayed (showing that the ref is fully working).
In TodoList, I'm using withStyles to add a blue border around the todo list to show that withStyles is working, and I'm displaying the primary color from the theme to show that withTheme is working.
TodoList.js
import React from "react";
import { connect } from "react-redux";
import Todo from "./Todo";
import { getTodosByVisibilityFilter } from "../redux/selectors";
import { withStyles, withTheme } from "#material-ui/core/styles";
import clsx from "clsx";
const styles = {
list: {
border: "1px solid blue"
}
};
const TodoList = React.forwardRef(({ todos, theme, classes }, ref) => (
<>
<div>theme.palette.primary.main: {theme.palette.primary.main}</div>
<ul ref={ref} className={clsx("todo-list", classes.list)}>
{todos && todos.length
? todos.map((todo, index) => {
return <Todo key={`todo-${todo.id}`} todo={todo} />;
})
: "No todos, yay!"}
</ul>
</>
));
const mapStateToProps = state => {
const { visibilityFilter } = state;
const todos = getTodosByVisibilityFilter(state, visibilityFilter);
return { todos };
};
export default connect(
mapStateToProps,
null,
null,
{ forwardRef: true }
)(withTheme(withStyles(styles)(TodoList)));
TodoApp.js
import React from "react";
import AddTodo from "./components/AddTodo";
import TodoList from "./components/TodoList";
import VisibilityFilters from "./components/VisibilityFilters";
import "./styles.css";
export default function TodoApp() {
const [renderIndex, incrementRenderIndex] = React.useReducer(
prevRenderIndex => prevRenderIndex + 1,
0
);
const todoListRef = React.useRef();
const heightDisplayRef = React.useRef();
React.useEffect(() => {
if (todoListRef.current && heightDisplayRef.current) {
heightDisplayRef.current.innerHTML = ` (height: ${
todoListRef.current.offsetHeight
})`;
}
});
return (
<div className="todo-app">
<h1>
Todo List
<span ref={heightDisplayRef} />
</h1>
<AddTodo />
<TodoList ref={todoListRef} />
<VisibilityFilters />
<button onClick={incrementRenderIndex}>
Trigger re-render of TodoApp
</button>
<div>Render Index: {renderIndex}</div>
</div>
);
}

imported component is not displayed

i've a component that i import, but its not displayed on the page.
this is my app.js file. i imported the <player/>component but it is not getting displayed properly on the browser.
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import { player } from "./player";
class App extends Component {
render() {
return (
<div className="App">
<div>
<player />
</div>
</div>
);
}
}
export default App;
this is the contents of the player.js
import React from "react";
import { Button } from "evergreen-ui";
export default class player extends React.Component {
constructor(...args) {
super(...args);
this.state = {
shoot: 0
};
}
shoot() {
this.setState.shoot = Math.floor(Math.random() * Math.floor(3));
}
render() {
return (
<div>
<h1>hello there</h1>
<h1>{this.state.shoot}</h1>
<Button onClick={() => this.shoot}>Shoot another
value</Button>
</div>
);
}
}
In your code, you've exported your player component as a default export
export default class player extemds React.Component
But in your import of it in the other file, you're importing it as a named export
import { player } from "./player";
Try importing it without the curly braces as you would with a default export
import player from "./player";
You are doing two mistakes:
1. Importing the component in the wrong way
2. Rendering the component in the wrong way
Solution
The component should be imported without the curly braces
The react component "player" is supposed to start with capital letters i.e. it should be renamed as Player
Below is the working code I have tried in my local machine. It only modifies App.js
import React, { Component } from "react";
import logo from "./logo.svg";
import "./App.css";
import Player from "./player"; // imported without curly braces and with capital first letter
class App extends Component {
render() {
return (
<div className="App">
<div>
<Player /> {/* Rendering the correct way */}
</div>
</div>
);
}
}
export default App;
Sidenote
In player.js, you are setting the state in the wrong fashion, it won't work because:
setState is a method and not a object
this is not binded with method shoot. It will throw error something like "cannot read this of undefined" or something
Modify your player.js as following:
import React from "react";
import { Button } from "evergreen-ui";
export default class player extends React.Component {
constructor(...args) {
super(...args);
this.state = {
shoot: 0
};
}
shoot = ()=>{
this.setState({
shoot: Math.floor(Math.random() * Math.floor(3)),
});
}
render() {
return (
<div>
<h1>hello there</h1>
<h1>{this.state.shoot}</h1>
<Button onClick={() => this.shoot()}>Shoot another
value</Button>
</div>
);
}
}
You have two main issues:
1) You export as default and then your import is wrong.
If you export as:
export default class player extemds React.Component
Then you need to import as:
import player from "./player";
2) Components must start uppercase, otherwise React thinks that they are simple HTML tags and not components.
So you must change player to Player everywhere

React exporting withRouter and withStyles error

I am using react along with redux and material-ui to make a component. I am attempting to write an export statement export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
However, this doesn't seem to work I get an error that says
TypeError: Cannot set property 'props' of undefined
this.props = props;
This error is referencing one of my node_modules.
Here is my full code:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import {withRouter} from 'react-router-dom'
import { withStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import Button from '#material-ui/core/Button';
const styles = theme =>({
root: {
maxWidth: 345,
},
})
class FirstPage extends Component {
state = {
feeling: ''
}
//This function will dispatch the users response to index.js
//The dispatch type here is 'SET_FEELING'
submitData=(event) => {
event.preventDefault();
this.props.dispatch({type: 'SET_FEELING', payload: this.state})
this.changeLocation();
}
//This function will update the local state with the users response
handleChange= (event) => {
this.setState({
feeling: event.target.value
})
}
//This function will change the current url when a button is clicked
changeLocation= ()=> {
this.props.history.push('/secondPage')
}
render(){
const { classes } = this.props;
return(
<div>
<Card >
<CardContent className={classes.root}>
<form>
<input onChange={this.handleChange} placeholder='How are you feeling' value={this.state.feeling} />
</form>
</CardContent>
<CardActions>
<Button onClick={this.submitData}>Submit</Button>
</CardActions>
</Card>
</div>
)
}
}
//this export connects the component to the reduxStore as well as allowing us to use the history props
export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
I believe the following code should work:
export default withRouter(connect()(withStyles(styles)(FirstPage)))
Instead of
export default connect()(withRouter(FirstPage))(withStyles(styles)(FirstPage))
First of all, connect() returns a function that only accepts an argument. Second, connect() should be wrapped inside withRouter(). This problem is stated in the github docs of React Router.
without using react-redux :
export default (withStyles(styles), withRouter)(FirstPage);

My mapStateToProps is not passing props to component

I am really newbie in Redux development. Just started two days ago
Before, I used props - state pattern but I am going to change some parts of state - props pattern to Redux.
First, I will show my codes. index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import ItemList from './itemList';
import SearchList from './searchList';
import {Provider,connect} from 'react-redux';
import {store} from './storeReducer';
import {backToMain} from './reduxAction';
class App extends React.Component{
// not important some codes
render(){
return(
<div>
<section id="Search">
<form action="//localhost:80/ReactStudy/travelReduxApp/public/server/itemList.php" id="Search" className="search" method="GET" onSubmit={this.submitForm}>
<input ref={'search'} placeholder="search country, attraction names" type="text" name="search"/>
<button type="submit">SEARCH</button>
</form>
<p className={this.state.validateError.display}>
{this.state.validateError.type=='invalid value'?
'Only english letters are available in this input'
: (this.state.validateError.type=='not found')?
'Nothing was found with this keyword. Try again'
:'Empty text field'
}
</p>
</section>
<ItemContainer initializeSearch={this.initializeSearch} searchList={this.state.searchItem}/>
</div>
)
}
}
class ItemContainer extends React.Component{
state={
viewMain:true
}
//some codes
showMain=()=>{
this.setState({
viewMain:true
})
this.props.initializeSearch();
store.dispatch(backToMain());
}
render(){
console.log('Item container');
console.log(this.props);
return(
<section id="ItemContainer">
{
this.props.searchList!=''?
<SearchList searchList={this.props.searchList} mainVisible={this.state.viewMain}/>
:
<ItemList toggleView={this.toggleView} mainVisible={this.state.viewMain}/>
}
<button onClick={this.showMain}>Back to main</button>
</section>
)
}
}
const mapStateToProps =(state)=>{
console.log('working'); //it doesn't show it.
return{
visible:state.visible
}
};
const wrappedSearchList = connect(mapStateToProps,null)(ItemContainer);
const Root = () => (
<Provider store={store}>
<App/>
</Provider>
);
ReactDOM.render(
<Root/>,
document.getElementById('App')
)
reduxAction.js
export function backToMain(){
return{
type:'BACK_TO_MAIN'
}
}
storeReducer.js
import {createStore} from 'redux';
import {backToMain} from './reduxAction';
export const initialState = {
visible:true
}
export const store = createStore(viewMainReducer,initialState);
export function viewMainReducer(state=initialState,action){
switch(action.type){
case 'BACK_TO_MAIN':
console.log('Back..');
return{
...state,
visible:true
}
break;
default: return state;
}
}
I am really newbie in Redux so maybe I did not understand official document perfectly but I know mapStateToProps must pass state to the component as props. In my case, the component should be ItemContainer component.
Problem is when ItemContainer component is rendered.
If I check with
console.log(this.props)
in ItemContainer's render method , in console I see only initializeSearch and searchList are passed to the component. I cannot figure out why my visible property of initialState object is not passed to the component. What could be the reason? What should I do to pass visible property to ItemContainer component?
React / Redux: mapStateToProps not actually mapping state to props
read this thread but I just did not understand ...
Try using wrappedSearchList instead of ItemContainer
<wrappedSearchList initializeSearch={this.initializeSearch} searchList={this.state.searchItem}/>**strong text**

Resources