setState is not updating or re rendering DOM or component - javascript

I cant figure out why my Login component is not re-rendering what is on the page. The state is changed to loginShow after I click on a "Log In" button on top of my form.
import React from 'react';
import SignUp from '../SignUp';
import Cards from '../Articles/Cards';
import Login from '../LogIn';
export default class Gecko extends React.Component {
constructor(props) {
super(props);
this.state = { requestedPostsThatWeGotFromGecko: null, }
this.clickMe = this.clickMe.bind(this)
this.state = {
loginStatus: "loginHide",
authType: "signup"
};
this.loginClose = this.loginClose.bind(this);
this.loginOpen = this.loginOpen.bind(this);
}
loginClose(e) {
e.stopPropagation();
this.setState({
loginStatus: "loginHide"
});
}
loginOpen() {
this.setState({
loginStatus: "loginShow"
});
}
clickMe = () => {
const {requestedPostsThatWeGotFromGecko} = this.state;
this.setState({ requestedPostsThatWeGotFromGecko: !requestedPostsThatWeGotFromGecko })
}
/* mainLogIn = () => {
const {loginStatus} = this.state;
this.setState({ loginStatus: 'loginHide' })
} */
render() {
const { requestedPostsThatWeGotFromGecko } = this.state;
const { loginStatus } = this.state;
console.log(loginStatus);
// const { authType } = this.state;
// if (loginStatus === "loginHide") return <SignUp login={() => this.clickMe()} />
// if (requestedPostsThatWeGotFromGecko.props === true) return <Cards />
if (loginStatus !== "loginShow") return (
<div className="gecko">
{requestedPostsThatWeGotFromGecko ? (
<Cards />
): (
<SignUp login={() => this.clickMe()} />
)
}
</div>
);
if (loginStatus === "loginShow") return <Login />
}
}
I believe the issue lies where I am trying to set what is being displayed using the conditional operator at the end of the code above. I have included where I am setting the state and props from my other components in the code below.
const onClick = () => {
this.props.login();
console.log('rich');
}
const mainLogIn = () => {
this.setState({
loginStatus: "loginShow"
});
console.log('rich1');
console.log(this.state);
}
const onClick = () => {
this.props.login();
console.log('rich');
}
const mainSignUp = () => {
this.props.signup();
this.setState({
loginStatus: "loginHide"
});
console.log('rich2');
}

Related

Saving state to localStorage [duplicate]

I have no idea How to store the react js state into localstorage.
import React, { Component } from 'react'
import './App.css';
import { auth,createUserProfileDocument } from './firebase/firebase.utils'
import { TodoForm } from './components/TodoForm/TodoForm.component'
import {TodoList} from './components/TodoList/TodoList.component'
import {Footer} from './components/footer/footer.component'
import Header from '../src/components/header/header.component'
import {Redirect} from 'react-router-dom'
import {connect} from 'react-redux'
import {setCurrentUser} from './redux/user/user.actions'
export class App extends Component {
constructor(props) {
super(props)
this.input=React.createRef()
this.state = {
todos:[
{id:0, content:'Welcome Sir!',isCompleted:null},
]
}
}
todoDelete = (id) =>{
const todos = this.state.todos.filter(todo => {
return todo.id !== id
})
this.setState({
todos
})
}
toDoComplete = (id,isCompleted) =>{
console.log(isCompleted)
var todos = [...this.state.todos];
var index = todos.findIndex(obj => obj.id === id);
todos[index].isCompleted = !isCompleted;
this.setState({todos});
console.log(isCompleted)
}
addTODO = (todo) =>{
todo.id = Math.random()
todo.isCompleted = true
let todos = [...this.state.todos, todo]
this.setState({
todos
})
}
unsubscribeFromAuth = null;
componentDidMount() {
const { setCurrentUser } = this.props;
this.unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
if (userAuth) {
const userRef = await createUserProfileDocument(userAuth);
userRef.onSnapshot(snapShot => {
setCurrentUser({
id: snapShot.id,
...snapShot.data()
});
});
}
setCurrentUser(userAuth);
});
}
componentWillUnmount() {
this.unsubscribeFromAuth();
}
render() {
return (
<div className='App'>
<Header />
<TodoForm addTODO={this.addTODO} />
<TodoList
todos={this.state.todos}
todoDelete={ this.todoDelete}
toDoComplete={ this.toDoComplete}
/>
<Footer/>
</div>
)
}
}
const mapStateToProps = ({ user }) => ({
currentUser: user.currentUser
});
const mapDispatchToProps = dispatch => ({
setCurrentUser: user => dispatch(setCurrentUser(user))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);
in my input Form
import './TodoForm.style.css'
export class TodoForm extends Component {
constructor(props) {
super(props)
this.state = {
content : ''
}
}
handleChange = (e) =>{
this.setState({
content: e.target.value
})
}
handleSubmit =(e) =>{
e.preventDefault();
this.props.addTODO(this.state);
this.setState({
content: ''
})
}
render() {
return (
<div className='inputTask'>
<form onSubmit={ this.handleSubmit}>
<input
className="textBox"
type='text'
onChange={ this.handleChange}
value={this.state.content}
placeholder='what you want to do ...'
/>
</form>
</div>
)
}
}
export default TodoForm
I have no idea How to store the react js state into localstorage.
i searched on internet but unable to find the exact solution all the codes that i think is necessary post.
You can use reactLocalStorage to save any data in local storage
import {reactLocalStorage} from 'reactjs-localstorage';
reactLocalStorage.set('var', true);
reactLocalStorage.get('var', true);
reactLocalStorage.setObject('var', {'test': 'test'});
reactLocalStorage.getObject('var');
reactLocalStorage.remove('var');
reactLocalStorage.clear();
Read out the localStorage item in the componentDidMount callback. Simply read the item you want to get, check if it exists and parse it to a usable object, array or datatype that need. Then set the state with the results gotten from the storage.
And to store it, simply handle it in an event handler or helper method to update both the state and the localStorage item.
class ExampleComponent extends Component {
constructor() {
super();
this.state = {
something: {
foo: 'bar'
}
}
}
componentDidMount() {
const storedState = localStorage.getItem('state');
if (storedState !== null) {
const parsedState = JSON.parse(storedState);
this.setState({ something: parsedState });
}
}
clickHandler = (event) => {
const value = event.target.value;
const stringifiedValue = JSON.stringify(value);
localStorage.setItem('state', stringifiedValue);
this.setState({ something: value });
}
render() {
return (
<button onClick={clickHandler} value={this.state.something}>Click me</button>
);
}
}
Set data in localStorage
key-value pair :
localStorage.setItem('key_name',"value");
object
localStorage.setItem('key_name', JSON.stringify(object));
Remove data from localStorage
localStorage.removeItem('key_name');
Get data from localStorage
let data = localStorage.getItem('key_name');
object :
let data = JSON.parse(localStorage.getItem('key_name'));
clear localStorage (delete all data)
localStorage.clear();

How to fix onClick element. ReactJS

I new in ReactJS and i have one few question. I defined function showModal and but console.log() and
this.setState({show:!this.state.show});.
And after that I applied
this function onClick event for div element inside map function.
1st question: When I click on div element showModal work but in console I don't see my console.log.
2nd question: I want to make when you click on one div element it must add/show few new div elements but only for one div element (on which I clicked). But now when I click on one div element it add/show new elements for all div elements which had this showModal function.
How can i fix this
import React, { Component } from "react";
import Modal from '../components/modal/form'
const DEFAULT_QUERY = 'redux';
const PATH_BASE = 'URL which work correct';
class Actions extends React.PureComponent{
constructor(){
super();
this.state = {
result:null,
show:false,
helpId:null
};
this.setSearchTopStories = this.setSearchTopStories.bind(this);
this.showModal = this.showModal.bind(this);
this.handleClickFromParent = this.handleClickFromParent.bind(this);
this.onClose = this.onClose.bind(this);
}
onClose = e => {
this.setState({ show: false});
}
handleClickFromParent = e => {
this.setState({show: !this.state.show});
}
showModal = e => {
console.log('BABE');
this.setState({show: !this.state.show})
};
setSearchTopStories(result) {
this.setState({ result });
};
componentDidMount() {
fetch(`${PATH_BASE}`)
.then(response => response.json())
.then(result => this.setSearchTopStories(result))
.catch(error => error);
};
render(){
const { searchTerm, result } = this.state;
console.log('* Actions Pure*');
console.log(result);
console.log('=');
return(
<div>
{
(result !== null) ?
result.map(
(item,index) =>
<div>
<div onClick={()=>this.showModal()}>{item.name}</div>
<Modal
id = {index}
handleClickFromParent {this.handleClickFromParent}
item = {[item]}
show = {this.state.show}
onClose = {this.onClose}>
YOLO
</Modal>
</div>
)
: null
}
</div>
)
}
}
export default Actions;
While selecting u can pass the item on method, and on click u can set the item value. Please check the below code.
Demo:
https://codesandbox.io/s/stackoverflowmodal-19i36
this.state = {
result: null,
show: false,
selectedItem:null,
helpId: null
};
//
showModal = (selectedItem) => {
this.setState({
show: !this.state.show,
selectedItem
});
};
//
class Actions extends React.PureComponent {
constructor() {
super();
this.state = {
result: null,
show: false,
selectedItem: null,
helpId: null
};
this.setSearchTopStories = this.setSearchTopStories.bind(this);
this.showModal = this.showModal.bind(this);
this.handleClickFromParent = this.handleClickFromParent.bind(this);
this.onClose = this.onClose.bind(this);
}
onClose = e => {
this.setState({
show: false
});
};
handleClickFromParent = e => {
this.setState({
show: !this.state.show
});
};
showModal = selectedItem => {
this.setState({
show: !this.state.show,
selectedItem
});
};
setSearchTopStories(result) {
this.setState({ result });
}
componentDidMount() {
fetch(`${PATH_BASE}`)
.then(response => response.json())
.then(result => this.setSearchTopStories(result))
.catch(error => error);
}
render() {
const { searchTerm, result, selectedItem } = this.state;
return (
<div>
{result && result.length
? result.map((item, index) => (
<div>
<div onClick={() => this.showModal(item)}>{item.name}</div>
</div>
))
: null}
{selectedItem && (
<Modal
id={index}
handleClickFromParent={this.handleClickFromParent}
item={[selectedItem]}
show={this.state.show}
onClose={this.onClose}
>
YOLO
</Modal>
)}
</div>
);
}
}
export default Actions;

Changing state of child component from parent with refs

I have a TaskList. I'm trying to display a child component TaskEdit (edit box for the task) several components lower, onClick of a button.
TaskEdit has a state variable hidden, set to true by default. How do I change the state inside the child component from within the child component?
React documentation mentions a forwardRef() function in order to reference the child component, but I haven't any luck so far with it.
Here's my code:
import TaskEdit from '../TaskEdit';
class TasksBase extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
tasks: [],
};
this.markTaskAsCompleted = this.markTaskAsCompleted.bind(this);
this.deleteTask = this.deleteTask.bind(this);
this.incrementDate = this.incrementDate.bind(this);
this.toggleTaskEdit = this.toggleTaskEdit.bind(this);
}
componentDidMount() {
this.onListenForTasks();
}
componentWillUnmount() {
this.unsubscribe();
}
render() {
const { tasks, loading } = this.state;
return (
<div>
{loading && <div>Loading ...</div>}
{tasks ? (
<TaskList tasks={tasks}
handleToggleEdit={this.toggleTaskEdit}
handleMarkCompleted={this.markTaskAsCompleted}
handleDeleteTask={this.deleteTask}
taskEditElement={this.editTaskElement}
/>
):(
<div>There are no tasks ...</div>
)}
</div>
);
}
onListenForTasks() {
this.setState({ loading: true });
this.unsubscribe = this.props.firebase
.tasks()
.orderBy('importance', 'desc')
.orderBy('urgency', 'desc')
.orderBy('created', 'desc')
.onSnapshot(snapshot => {
if (snapshot.size) {
let tasks = [];
snapshot.forEach(doc =>
tasks.push({ ...doc.data(), uid: doc.id }),
);
this.setState({
tasks: tasks,
loading: false
});
} else {
this.setState({ tasks: null, loading: false });
}
});
}
markTaskAsCompleted(task){
// Some code
}
deleteTask(id){
// Some code
}
toggleEditTask(){
this.editTaskElement.current.toggle();
}
}
const Tasks = withFirebase(TasksBase);
const TaskList = ({ tasks, handleToggleEdit, handleMarkCompleted, handleDeleteTask }) => (
<ul className="tasks">
{tasks.map( task => (
<Task key={task.uid}
task={task}
handleToggleEdit={handleToggleEdit}
handleMarkCompleted={handleMarkCompleted}
handleDeleteTask={handleDeleteTask}
/>
))}
</ul>
);
const Task = ({ task, handleToggleEdit, handleMarkCompleted, handleDeleteTask}) => (
(!task.completed && !task.obsolete && !task.waitingForDependencies) && (!task.start || task.start.toMillis() <= Date.now()) &&
<li className="task">
<strong>{task.userId}</strong> {task.name}
{ task.estimate &&
<span>{task.estimate.amount + task.estimate.unit}</span>
}
<div className="icons">
<FontAwesomeIcon icon="edit" onClick={() => handleToggleEdit(task)} />
<FontAwesomeIcon icon="check-circle" onClick={() => handleMarkCompleted(task)} />
<FontAwesomeIcon icon="times-circle" onClick={() => handleDeleteTask(task.uid)}/>
</div>
<TaskEdit task={task} />
</li>
);
const condition = authUser => !!authUser;
export default compose(
withEmailVerification,
withAuthorization(condition),
)(Tasks);
TaskEdit:
import React, { Component } from 'react';
import { withFirebase } from '../Firebase';
const INITIAL_STATE = {
hidden: true,
};
class TaskEditBase extends Component {
constructor(props) {
super(props);
this.state = { ...INITIAL_STATE };
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
console.log("name " + name);
console.log("value " + value);
this.setState({
[name]: value
});
}
toggle(){
this.setState({
hidden: !this.prevState.hidden
})
}
onSumbitTaskEdit = (event) => {
event.preventDefault();
};
render(){
return(
!this.state.hidden &&
<div className="task-edit">
<form onSubmit={this.onSumbitTaskEdit}>
<div>A bunch of inputs</div>
<input type="submit" value="Edit"/>
</form>
</div>
)
}
}
const TaskEdit = withFirebase(TaskEditBase);
export default TaskEdit;

Trying to set up form validation in my basic todo list app

I am trying to set up validations in my todo list app in react; however this doesn't seem to work. Even if the form is empty the process still goes through and I don't know where the problem is coming from. I am just following a tutorial online since I'm pretty new to this and don't know how to do it myself.
import React from "react";
import * as TodoActions from "../actions/TodoActions";
import TodoStore from "../stores/TodoStore";
import Todo from './Todo.js'
import './Todos.css'
const formValid = ({ formErrors, ...rest }) => {
let valid = true;
Object.values(formErrors).forEach(val => {
val.length > 0 && (valid = false);
});
Object.values(rest).forEach(val => {
val === null && (valid = false);
});
return valid;
};
export default class Todos extends React.Component {
constructor() {
super();
this.state = {
todos: TodoStore.getAll(),
loading: true,
formErrors: {
todo: ""
}
};
TodoActions.receiveTodos()
}
componentWillMount() {
TodoStore.addChangeListener(this.getTodos);
}
componentWillUnmount() {
TodoStore.removeChangeListener(this.getTodos);
}
componentDidUpdate() {
TodoActions.receiveTodos();
}
getTodos = () => {
this.setState({
todos: TodoStore.getAll(),
loading: false
});
}
deleteTodo = (id) => {
TodoActions.deleteTodo(id);
}
addItem = (e) => {
e.preventDefault();
TodoActions.createTodo(this._inputElement.value)
}
handleChange = e => {
e.preventDefault();
const { name, value } = e.target;
let formErrors = { ...this.state.formErrors };
switch (name) {
case "todo":
formErrors.todo =
value.length < 0 ? "Task cannot be empty" : "";
break;
default:
break;
}
this.setState({ formErrors, [name]: value }, () => console.log(this.state));
}
render() {
const { todos } = this.state;
const { formErrors } = this.state;
let TodoComponents;
if (this.state.loading) {
TodoComponents = <h1>Loading...</h1>;
} else if(todos.length) {
TodoComponents = todos.map((todo) => {
return (
<div key={todo.id} className="todo-list">
<Todo key={todo.id} name={todo.name}/>
<div className="todo-btn"><a type="button" onClick={() => this.deleteTodo(todo.id)} className="delete-btn"><i class="fas fa-trash-alt"></i></a></div>
</div>
)
});
} else {
TodoComponents = <p>No tasks to show :)</p>
}
return (
<div className="main-container">
<div className="small-container">
<h1 className="title">All Tasks</h1>
<ul>{TodoComponents}</ul>
<form onSubmit={this.addItem}>
<input ref={(a) => this._inputElement = a} placeholder="Enter Task" className="input-form {formErrors.todo.length < 0 ? 'error' : null}"/>
{formErrors.todo.length < 0 && (
<span className="errorMessage">{formErrors.firstName}</span>
)}
<button type="submit" className="input-btn">Add</button>
</form>
</div>
</div>
);
}
}

Converting a stateful component to stateless

i'm pretty new to react and redux and i'm having an issue here. It's mandatory to use only stateless components with containers whenever state handing is required. These two components are:
import React from 'react';
import DatePicker from '../DatePicker';
class DayInput extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
dateValue: new Date(),
activeDateWidget: false,
};
}
changeDate(date) {
this.setState({
dateValue: date,
});
}
changeActiveDateWidget(e) {
e.stopPropagation();
this.setState({
activeDateWidget: !this.state.activeDateWidget,
});
}
render() {
const { input, meta } = this.props;
const { dateValue, activeDateWidget } = this.state;
return (
<div>
<input
{...input}
className="form-control"
type="text"
value={dateValue}
onClick={this.changeActiveDateWidget}
// onBlur={this.changeActiveDateWidget}
/>
{activeDateWidget ? (
<div>
<DatePicker
changeActiveDateWidget={this.changeActiveDateWidget}
changeDate={this.changeDate}
dateValue={dateValue}
/>
</div>
) : (
<div />
)}
</div>
);
}
}
export default DayInput;
import React from 'react';
import 'react-day-picker/lib/style.css';
import DayPicker, { DateUtils } from 'react-day-picker';
class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
selectedDay: new Date(),
};
}
componentDidMount() {
if (this.input) {
this.input.focus();
}
}
handleDayClick(e, day, { disabled }) {
e.stopPropagation();
if (disabled) {
return;
}
this.setState({ selectedDay: day }, () => {
this.props.changeDate(day);
this.props.changeActiveDateWidget();
});
}
focusThisComponent(e) {
if (e) {
this.input = e;
}
}
render() {
const { changeActiveDateWidget } = this.props;
const { selectedDay } = this.state;
return (
<div
ref={this.focusThisComponent}
tabIndex="1"
>
<DayPicker
id="THISTHING"
initialMonth={selectedDay}
selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
onDayClick={this.handleDayClick}
/>
</div>
);
}
}
export default DatePicker;
As you can see the first component is wrapped inside the second component. I tried to convert the first component myself like this:
const DayInput = props => {
<input
{...props.input}
type="text"
value= {new Date()}
onClick={()=>??}
/>
}
but as you can see i dont know how to handle the onclick event. Can someone help me to achieve this?
To turn your component in a stateless component, you must pass everything as properties of the component.
This will be your DayInput splitted into 2 components :
const DayInputShow = props => {
return (<input
{...props.input}
type="text"
value= {props.value}
onClick={(event)=>props.onClick()}
/>);
};
const DayInputEdit = props => {
return (<DatePicker
changeActiveDateWidget={props.changeActiveDateWidget}
changeDate={props.onChange}
dateValue={props.value}
/>);
};
DayInputShow.propTypes = {
value: PropTypes.date,
onClick: PropTypes.func,
}
DayInputEdit.propTypes = {
value: PropTypes.date,
onChange: PropTypes.func,
}
And this will be the root component (uncomplete and still statefull) :
class DatePicker extends React.Component { // eslint-disable-line react/prefer-stateless-function
constructor(props) {
super(props);
this.state = {
selectedDay: new Date(),
};
}
componentDidMount() {
if (this.input) {
this.input.focus();
}
}
handleDayClick(e, day, { disabled }) {
e.stopPropagation();
if (disabled) {
return;
}
this.setState({ selectedDay: day }, () => {
this.props.changeDate(day);
this.props.changeActiveDateWidget();
});
}
focusThisComponent(e) {
if (e) {
this.input = e;
}
}
render() {
const { changeActiveDateWidget } = this.props;
const { selectedDay } = this.state;
let dayPicker;
if (this.input) {
dayPicker = <DayPickerEdit
value={this.state.selectedDay}
onChange={(value) => {this.setState({selectedDay: value})}}
selectedDays={day => DateUtils.isSameDay(selectedDay, day)}
onDayClick={this.handleDayClick}
/>
} else {
dayPicker = <DayPickerShow
value={this.state.selectedDay}
ref={(input) => { this.inputRef = input; }} />
onClick={() => {this.focusThisComponent(this.inputRef )}}
/>
}
return (
<div
ref={this.focusThisComponent}
tabIndex="1"
>
{dayPicker }
</div>
);
}
}
export default DatePicker;

Categories