Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 以正确的方式刷新表数据_Javascript_Reactjs_React Redux - Fatal编程技术网

Javascript 以正确的方式刷新表数据

Javascript 以正确的方式刷新表数据,javascript,reactjs,react-redux,Javascript,Reactjs,React Redux,我有一个返回两个组件的容器——一个用于添加新旅程的表单和一个用于列出所有旅程的表。表格和表格都在同一页上 在表中,我添加了一个可单击的单元格来编辑/删除旅程。虽然我可以删除给定的旅程,但在尝试呈现表时,页面会立即中断,因为其中一个旅程已不存在 实现此功能的最佳方法是什么?我可以在同一页面中添加/编辑/删除行程,并在数据发生更改时使用更新的数据刷新表 journeysAdmin容器: class JourneysAdmin extends Component { componentDidMou

我有一个返回两个组件的容器——一个用于添加新旅程的表单和一个用于列出所有旅程的表。表格和表格都在同一页上

在表中,我添加了一个可单击的单元格来编辑/删除旅程。虽然我可以删除给定的旅程,但在尝试呈现表时,页面会立即中断,因为其中一个旅程已不存在

实现此功能的最佳方法是什么?我可以在同一页面中添加/编辑/删除行程,并在数据发生更改时使用更新的数据刷新表

journeysAdmin
容器:

class JourneysAdmin extends Component {
  componentDidMount() {
    this.props.onFetchJourneys(this.props.token, this.props.userId);
  }

  renderTableHeader() {
    return (
      <TableHead>
        <TableRow>
          <TableCell>ID</TableCell>
          <TableCell>Name</TableCell>
          <TableCell>Description</TableCell>
          <TableCell>Progress</TableCell>
          <TableCell>Journey Points</TableCell>
          <TableCell>Journey Status</TableCell>
        </TableRow>
      </TableHead>
    );
  }

  render() {
    let journeys = <Spinner />;
    if (!this.props.loading) {
      journeys = this.props.journeys.map(journey => (
        <JourneyAdmin
          key={journey._id}
          journeyID={journey._id}
          name={journey.name}
          description={journey.description}
          progress={journey.journeyPoints}
          journeyPoints={journey.journeyPoints}
          journeyStatus={journey.status}
          journeyUserType={journey.journeyUserType}
          isAuthenticated={this.props.user.isAuthenticated}
          role={this.props.user.role}
          lessons={journey.lessons}
          journeyClicked={() =>
            this.props.onJourneyClicked(
              this.props.token,
              journey._id,
              this.props.userId
            )
          }
          deleteJourney={() =>
            this.props.onJourneyDeleted(journey._id, this.props.token)
          }
        />
      ));
    }
    return (
      <Paper>
        <JourneyAdminForm
          createjourney={(
            journeyName,
            journeyDescription,
            journeyPoints,
            journeyLevel,
            journeyTime,
            lessonName,
            lessonShortDescription,
            lessonDescription,
            lessonExampleText
          ) =>
            this.props.onAddJourney(
              journeyName,
              journeyDescription,
              journeyPoints,
              journeyLevel,
              journeyTime,
              lessonName,
              lessonShortDescription,
              lessonDescription,
              lessonExampleText,
              this.props.token
            )
          }
        />
        <Table>
          {this.renderTableHeader()}
          {journeys}
        </Table>
      </Paper>
    );
  }
}

const mapStateToProps = state => {
  return {
    journeys: state.journey.journeys,
    loading: state.journey.loading,
    token: state.auth.token,
    userId: state.auth.userId,
    user: state.auth
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onFetchJourneys: (token, userId) =>
      dispatch(actions.fetchJourneys(token, userId)),
    onJourneyDeleted: (journeyID, token) =>
      dispatch(actions.deleteJourney(journeyID, token)),
    onAddJourney: (
      journeyName,
      journeyDescription,
      journeyPoints,
      journeyLevel,
      journeyTime,
      lessonName,
      lessonShortDescription,
      lessonDescription,
      lessonExampleText,
      token
    ) =>
      dispatch(
        actions.addJourney(
          journeyName,
          journeyDescription,
          journeyPoints,
          journeyLevel,
          journeyTime,
          lessonName,
          lessonShortDescription,
          lessonDescription,
          lessonExampleText,
          token
        )
      )
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(withErrorHandler(JourneysAdmin, axios));
JourneysAdmin
表格组件:

class JourneyAdminForm extends Component {
  state = {
    controls: {
      Name: {
        elementType: "input",
        elementConfig: {
          placeholder: "Name"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      Description: {
        elementType: "input",
        elementConfig: {
          placeholder: "Description"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      Points: {
        elementType: "input",
        elementConfig: {
          placeholder: "Points"
        },
        value: "",
        validation: {
          required: true,
          min: 100,
          max: 999,
          isNumeric: true
        },
        valid: false,
        touched: false
      },
      Level: {
        elementType: "input",
        elementConfig: {
          placeholder: "Level"
        },
        value: "",
        validation: {
          required: true,
          minLength: 1
        },
        valid: false,
        touched: false
      },
      journeyTime: {
        elementType: "input",
        elementConfig: {
          placeholder: "Journey time"
        },
        value: "",
        validation: {
          minLength: 2,
          isNumeric: true
        },
        valid: false,
        touched: false
      },
      lessonName: {
        elementType: "input",
        elementConfig: {
          placeholder: "Lesson Name"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      lessonShortDescription: {
        elementType: "input",
        elementConfig: {
          placeholder: "Lesson short-description"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      lessonDescription: {
        elementType: "input",
        elementConfig: {
          placeholder: "Lesson description"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      },
      lessonExampleText: {
        elementType: "input",
        elementConfig: {
          placeholder: "Lesson example text"
        },
        value: "",
        validation: {
          required: true,
          minLength: 8
        },
        valid: false,
        touched: false
      }
    }
  };

  checkValidity(value, rules) {
    let isValid = true;
    if (!rules) {
      return true;
    }

    if (rules.required) {
      isValid = value.trim() !== "" && isValid;
    }

    if (rules.minLength) {
      isValid = value.length >= rules.minLength && isValid;
    }

    if (rules.maxLength) {
      isValid = value.length <= rules.maxLength && isValid;
    }

    if (rules.isEmail) {
      const pattern = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
      isValid = pattern.test(value) && isValid;
    }

    if (rules.isNumeric) {
      const pattern = /^\d+$/;
      isValid = pattern.test(value) && isValid;
    }

    return isValid;
  }

  inputChangedHandler = (event, controlName) => {
    let updatedControls = {
      ...this.state.controls,
      [controlName]: {
        ...this.state.controls[controlName],
        value: event.target.value,
        valid: this.checkValidity(
          event.target.value,
          this.state.controls[controlName].validation
        ),
        touched: true
      }
    };
    this.setState({ controls: updatedControls });
  };

  submitHandler = event => {
    event.preventDefault();
    console.log("Create button on JourneyAdmin page was clicked");
    this.props.createjourney(
      this.state.controls.Name.value,
      this.state.controls.Description.value,
      this.state.controls.Points.value,
      this.state.controls.Level.value,
      this.state.controls.journeyTime.value,
      this.state.controls.lessonName.value,
      this.state.controls.lessonShortDescription.value,
      this.state.controls.lessonDescription.value,
      this.state.controls.lessonExampleText.value
    );
  };

  render() {
    const formElementsArray = [];

    for (let key in this.state.controls) {
      formElementsArray.push({
        id: key,
        config: this.state.controls[key]
      });
    }

    let form = null;
    form = formElementsArray.map(formElement => (
      <Input
        key={formElement.id}
        elementType={formElement.config.elementType}
        elementConfig={formElement.config.elementConfig}
        value={formElement.config.value}
        invalid={!formElement.config.valid}
        shouldValidate={formElement.config.validation}
        touched={formElement.config.touched}
        changed={event => this.inputChangedHandler(event, formElement.id)}
      />
    ));

    if (this.props.loading) {
      form = <Spinner />;
    }

    let errorMessage = null;

    if (this.props.status === "fail") {
      errorMessage = <p>Journey could not be added because of errors!</p>;
    } else if (this.props.status === "success") {
      errorMessage = <p>New Journey has been created!!</p>;
    }

    return (
      <div>
        <form onSubmit={this.submitHandler}>
          {form}
          <button btnType="Success">Create</button>
        </form>
        {errorMessage}
      </div>
    );
  }
}

export default JourneyAdminForm;
class JourneyAdmin extends Component {

  handleEditClick = (id, column) => {
    return event => {
      console.log(`You will Edit row with id ${id}, Name: ${column}.`);
    };
  };

  handleDeleteClick = (id, column) => {
    return event => {
      console.log(`You will delete on row with id ${id}, Name: ${column}.`);
      this.props.deleteJourney(this.props.journeyID);
    };
  };

  render() {
    return (
      <Aux>
        <TableBody>
          <TableRow key={this.props.journeyID}>
            <TableCell>{this.props.journeyID}</TableCell>
            <TableCell>{this.props.name}</TableCell>
            <TableCell>{this.props.description}</TableCell>
            <TableCell>{this.props.progress}</TableCell>
            <TableCell>{this.props.journeyPoints}</TableCell>
            <TableCell>{this.props.journeyStatus}</TableCell>
            <TableCell
              onClick={this.handleEditClick(
                this.props.journeyID,
                this.props.name
              )}
            >
              EDIT
            </TableCell>
            <TableCell
              onClick={this.handleDeleteClick(
                this.props.journeyID,
                this.props.name
              )}
            >
              Delete
            </TableCell>
          </TableRow>
        </TableBody>
      </Aux>
    );
  }
}

export default JourneyAdmin;
类JourneyAdmin扩展组件{
HandleEdit单击=(id,列)=>{
返回事件=>{
log(`您将编辑id为${id}、名称为${column}的行。`);
};
};
handleDeleteClick=(id,列)=>{
返回事件=>{
log(`您将删除id为${id}、名称为${column}的行。`);
this.props.deleteJourney(this.props.journeyID);
};
};
render(){
返回(
{this.props.journeyID}
{this.props.name}
{this.props.description}
{this.props.progress}
{this.props.journeyPoints}
{this.props.journeyStatus}
编辑
删除
);
}
}
导出默认的JourneyAdmin;

终于找到了问题所在。在我的操作/还原程序中没有正确添加/删除行程。每次我将旅程添加到DB中时,我都没有将它添加到状态中的
journes
对象中,也没有再次从DB获取旅程以将更新的列表添加到状态中

类似地,在删除时,在执行删除之后,我没有获取旅程。因此状态没有更新

现在我做的一切都是从行动开始的:

axios
      .post(journeyjurl, newJourney)
      .then(res => {
        const addedJourney = [];
        for (let key in res) {
          addedJourney.push({
            ...res.data[key],
            id: key
          });
        }
        dispatch(addJourneySuccess(addedJourney[0].data));
      })
在减速器中:

const addJourneysSuccess = (state, action) => {
  return updateObject(state, {
    journeys: state.journeys.concat(action.addedjourney),
    loading: false
  });
};
在删除操作中:

  axios
      .delete(journeyjurl)
      .then(res => {
        dispatch(deleteJourneySuccess());
        dispatch(fetchJourneys(token, ""));
      })
我还发现,从调用添加/删除操作的容器/组件调用
fetchjournies
(例如:在
handleDeleteClick
)也可以工作。基本上我在上面的评论中提到了1和3


希望这有助于像我这样的noob在未来

以下是我能想到的方法:1。将
fetchjournies
调用添加到
handleDeleteClick
2。每当有表单提交3时,使用组件生命周期方法(哪一种??)刷新数据。以某种方式链接操作,使得
onJourneyDeleted
也会分派
fetchjournes
这三种方法中哪一种是最好的/推荐的实现方法?有更好的方法吗?