问题描述
我有一个按钮,应该将我的笔记存档并将其发送到单独的存档选项卡。我具有以下设置,但是,当我单击以存档该帖子时,它将需要一击,而单击以取消存档该帖子将需要两次。我相信这是因为setstate是在更新调用之后异步发生的,但是我不确定解决方案。我试过为存档调用的更新制作一个单独的函数,但是没有运气。有什么想法吗?
我还不能嵌入图像,所以这是有问题的代码。
完整的代码故障(目前马虎)。
此组件确定通过道具传递到待办事项列表的类别。
import React from 'react';
import TodoListContainer from './todo_list_container';
class Left extends React.Component {
constructor(props){
super(props);
this.state = {
category: "keeps"
}
this.activateKeeps = this.activateKeeps.bind(this);
this.activateArchive = this.activateArchive.bind(this);
this.activateTrash = this.activateTrash.bind(this);
}
activateKeeps(e){
e.preventDefault();
this.setState({ category: "keeps" })
}
activateArchive(e){
e.preventDefault();
this.setState({ category: "archive" })
}
activateTrash(e){
e.preventDefault();
this.setState({ category: "trash"})
}
render(){
let categ = this.state.category
return(
<div>
<div className="left-bar">
<div className="keeps" onClick={this.activateKeeps}>KEEPS</div>
<div className="archive" onClick={this.activateArchive}>ARCHIVE</div>
<div className="trashed" onClick={this.activateTrash}>TRASH</div>
</div>
<TodoListContainer category={categ} />
</div>
)
}
}
容器
import TodoList from './todo_list';
import {createTodo,deleteTodo,fetchTodos,receiveTodos,updateTodo,receiveTodo,removeTodo } from '../../actions/todo_actions';
import { allTodos } from '../../reducers/selectors';
const mapStateToProps = state => ({
todos: allTodos(state),sessionId: state.session.id,state
});
const mapDispatchToProps = dispatch => ({
receiveTodo: todo => dispatch(receiveTodo(todo)),removeTodo: todo => dispatch(removeTodo(todo)),fetchTodos: () => dispatch(fetchTodos()),createTodo: todo => dispatch(createTodo(todo)),deleteTodo: todo => dispatch(deleteTodo(todo)),updateTodo: todo => dispatch(updateTodo(todo))
});
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
容器中的组件将根据通过componentWillReceiveProps中的props向下推的类别进行渲染(我需要更改它的日期,但它似乎正在起作用)
import TodoListItem from './todo_list_item';
import TodoForm from './todo_form';
import Preclick from './preclick_form';
import Nav from './nav_container.jsx';
class TodoList extends React.Component{
constructor(props){
super(props)
this.state = {
isEdit: false,searchText: '',category: this.props.category
}
this.handleClick = this.handleClick.bind(this);
this.handleClickOff = this.handleClickOff.bind(this);
this.updateSearch = this.updateSearch.bind(this);
}
componentDidMount() {
this.props.fetchTodos();
}
componentWillReceiveProps(nextProps){
this.setState({category: nextProps.category})
}
handleClick(e) {
e.stopPropagation();
this.setState({ isEdit: true });
}
handleClickOff(e){
this.setState({ isEdit: false });
}
updateSearch(e){
this.setState({searchText: e});
}
render() {
let searchText = this.state.searchText;
let category = this.state.category;
const { todos,removeTodo,createTodo,updateTodo } = this.props;
let todoItems;
if(category === "keeps"){
todoItems = todos.map(function(todo){
if ((searchText === '' || todo.title.includes(searchText) || todo.body.includes(searchText)) && (todo.archive === false && todo.trashed === false)){
return <TodoListItem
key={`todo-list-item${todo.id}`}
todo={todo}
receiveTodo={receiveTodo}
removeTodo={removeTodo}
deleteTodo={deleteTodo}
updateTodo={updateTodo}
/>
}
}
);
} else if(category === "archive"){
todoItems = todos.map(function (todo) {
if ((searchText === '' || todo.title.includes(searchText) || todo.body.includes(searchText)) && (todo.archive === true && todo.trashed === false)) {
return <TodoListItem
key={`todo-list-item${todo.id}`}
todo={todo}
receiveTodo={receiveTodo}
removeTodo={removeTodo}
deleteTodo={deleteTodo}
updateTodo={updateTodo}
/>
}
}
);
} else if(category === "trash"){
todoItems = todos.map(function (todo) {
if ((searchText === '' || todo.title.includes(searchText) || todo.body.includes(searchText)) && todo.trashed === true) {
return <TodoListItem
key={`todo-list-item${todo.id}`}
todo={todo}
receiveTodo={receiveTodo}
removeTodo={removeTodo}
deleteTodo={deleteTodo}
updateTodo={updateTodo}
/>
}
}
);
}
let form;
if(category === "trash" || category === "archive"){
form = <div className="no-form"></div>
} else {
form = (!this.state.isEdit) ? <Preclick /> : <TodoForm receiveTodo={receiveTodo} createTodo={createTodo} sessionId={this.props.sessionId} />
}
return (
// add handleClickOff here or another solution.
<div onClick={this.handleClickOff}>
<Nav updateSearch = {this.updateSearch}/>
<div className="formToggle" onClick={this.handleClick}>
{form}
</div>
<div className="notes">
{todoItems}
</div>
</div>
)}
}
export default TodoList;
加入该组件中的列表项
import React from 'react';
import { uniqueId } from '../../util/id_generator';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faSearch,faDrumstickBite,faThList,faArchive } from '@fortawesome/free-solid-svg-icons';
import OutsideClickHandler from 'react-outside-click-handler';
class TodoListItem extends React.Component{
constructor(props) {
super(props);
this.state = {
todo: this.props.todo,color: this.props.todo.color,title: this.props.todo.title,body: this.props.todo.body,archive: false,editing: false,id: this.props.todo.id,optionsOpen: false,isHovering: false,trashed: this.props.todo.trashed
}
this.update = this.update.bind(this);
this.handleUpdate = this.handleUpdate.bind(this);
this.archive = this.archive.bind(this);
this.openOptions = this.openOptions.bind(this);
this.handleMouseHover = this.handleMouseHover.bind(this);
this.handleClose = this.handleClose.bind(this);
this.clickOffNote = this.clickOffNote.bind(this);
}
update(property) {
return e => this.setState({ [property]: e.target.value });
}
handleUpdate(e) {
e.preventDefault();
const todo = Object.assign({},this.state,{ id: this.state.id });
this.props.updateTodo(todo);
this.setState({editing: false});
}
openOptions(e) {
e.preventDefault();
if (this.state.optionsOpen === false) {
this.setState({ optionsOpen: true })
} else {
this.setState({ optionsOpen: false })
}
}
handleMouseHover() {
this.setState({isHovering: true});
}
handleClose(){
if(this.state.optionsOpen === false){
this.setState({isHovering: false})
}
}
clickOffNote(){
this.setState({editing:false,isHovering: false});
}
archive() {
this.setState(prevState => ({
...prevState,archive: !prevState.archive
}),() => {
const todo = Object.assign({},{ id: this.state.id });
this.props.updateTodo(todo)
})
}
render(){
const {todo,updateTodo} = this.props;
let color;
color = this.props.todo.color + "Note";
let steev;
let options;
if(this.state.editing === true){
steev = <div className={color}>
<input className="title" placeholder={this.state.title} onChange={this.update('title')} />
<label className="formBodyContainer">
<textarea className="formBody" placeholder={this.state.body} onChange={this.update('body')} />
</label>
<button className="editButton" onClick={this.handleUpdate}>Submit Edit</button>
</div>
} else {
steev =
<div className="test" >
<div className={color} onMouseEnter={this.handleMouseHover}
onMouseLeave={this.handleClose}>
<div className="noteTitle">{this.state.title}</div>
<div className="noteBody">{this.state.body}</div>
{
this.state.isHovering &&
<div>
<FontAwesomeIcon icon="ellipsis-v" className="noteOptionsToggle" onClick={this.openOptions} />
<FontAwesomeIcon icon="archive" className="archiveOptionsToggle" onClick={this.archive} />
</div>
}
{
this.state.isHovering === false &&
<div className="optionsHolder">
</div>
}
{
this.state.optionsOpen &&
<OutsideClickHandler onOutsideClick={this.clickOffNote}>
<div className="options">
<button className="deleteButton" onClick={() => this.setState({ editing: true,optionsOpen: false })}>Edit Steev</button>
<button className="deleteButton" onClick={() => deleteTodo(todo)}>Delete Steev</button>
</div>
</OutsideClickHandler>
}
</div>
</div>
}
return(
<div>
{steev}
{options}
</div>
)}
}
export default TodoListItem;
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)