Reactjs 重复发送两个调度,然后第一个调度丢失

Reactjs 重复发送两个调度,然后第一个调度丢失,reactjs,redux,dispatch,Reactjs,Redux,Dispatch,我学习了React Javascript和Redux,现在我遇到了这个问题 这里有一个 试着这样做: 搜索书名“dep” 观看日志显示“搜索url为:”,此时应显示“开始图书搜索…” 我先发送两个Reduxdispatch,然后再发送一个,第一个再也不会发送 基本上是这样的: 我有一个用于学习的图书搜索应用程序,当按Search for a Book时,应用程序中会出现一个dispatch 这是发送状态的类: import { booksActionTypes } from ".

我学习了React Javascript和Redux,现在我遇到了这个问题

这里有一个

试着这样做:

  • 搜索书名“dep”
  • 观看日志显示“搜索url为:”,此时应显示“开始图书搜索…”
我先发送两个Redux
dispatch
,然后再发送一个,第一个再也不会发送

基本上是这样的:

我有一个用于学习的图书搜索应用程序,当按Search for a Book时,应用程序中会出现一个
dispatch

这是发送状态的类:

import { booksActionTypes } from "./books.types";

export const showLog = () => ({
  type: booksActionTypes.SHOWLOG,
});

export const setLogMessage = (log) => ({
  type: booksActionTypes.LOG_MESSAGE,
  payload: log,
});

export const clearPosts = () => ({
  type: booksActionTypes.CLEAR_POSTS,
});

export const requestStart = () => ({
  type: booksActionTypes.REQUEST_START,
});

export const requestSuccess = (booksList) => ({
  type: booksActionTypes.REQUEST_SUCCESS,
  payload: booksList,
});

export const requestFailure = (errMsg) => ({
  type: booksActionTypes.REQUEST_FAILURE,
  payload: errMsg,
});

export const actionCreators = {
  // "applicationUrl": "http://localhost:51374", http://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?title=dep&author=&genre=&price=
  // "sslPort": 44378
  requestBooks: (book) => async (dispatch, getState) => {
    dispatch(requestStart());
    dispatch(
      setLogMessage(() => ({
        message: "Starting books search..",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );

    var queryString = Object.keys(book)
      .map((key) => {
        return encodeURIComponent(key) + "=" + encodeURIComponent(book[key]);
      })
      .join("&");
    var url =
      "htftp://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?" +
      queryString;
    dispatch(
      setLogMessage(() => ({
        message: "Search url is: ",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );
    dispatch(
      setLogMessage(() => ({
        message: "Sdsadsasada: ",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );
    await fetch(url)
      .then((res) => res.json())
      .then((xml) => {
        dispatch(requestSuccess(xml));
      })
      .catch((errMsg) => {
        console.log(errMsg);
        dispatch(requestFailure(errMsg));
        fetch("books.xml")
          .then((res) => res.text())
          .then((xmlString) => getFromLocalDatabas(dispatch, xmlString, book))
          .catch((err) => {
            dispatch(requestFailure(errMsg));
          });
      });
  },
};
function getFromLocalDatabas(dispatch, xmlFile, book) {
  var parser = new window.DOMParser();
  var xmlDoc = parser.parseFromString(xmlFile, "text/xml");
  var books = xmlDoc.documentElement.childNodes;
  var map = [];
  for (var i = 0; i < books.length; i++) {
    var author = books[i]
      .getElementsByTagName("author")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var title = books[i]
      .getElementsByTagName("title")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var genre = books[i]
      .getElementsByTagName("genre")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var price = books[i]
      .getElementsByTagName("price")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var publish_date = books[i]
      .getElementsByTagName("publish_date")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var description = books[i]
      .getElementsByTagName("description")[0]
      .childNodes[0].nodeValue.toLowerCase();

    if (book.author && author.indexOf(book.author.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.title && title.indexOf(book.title.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.genre && genre.indexOf(book.genre.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.price && price.indexOf(book.price.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (
      book.publish_date &&
      publish_date.indexOf(book.publish_date.toLowerCase()) >= 0
    ) {
      sendBackThisBook(map, books[i]);
    }
    if (
      book.description &&
      description.indexOf(book.description.toLowerCase()) >= 0
    ) {
      sendBackThisBook(map, books[i]);
    }
  }
  dispatch(requestSuccess(map));
}

function sendBackThisBook(map, book) {
  var index = map.findIndex((x) => x.id == book.getAttribute("id"));
  if (index != -1) {
    console.log(`exist skipping `, book.getAttribute("id"));
    return;
  }
  map.push({
    id: book.getAttribute("id"),
    title: book.getElementsByTagName("title")[0].childNodes[0].nodeValue,
    author: book.getElementsByTagName("author")[0].childNodes[0].nodeValue,
    genre: book.getElementsByTagName("genre")[0].childNodes[0].nodeValue,
    price: book.getElementsByTagName("price")[0].childNodes[0].nodeValue,
    publish_date: book.getElementsByTagName("publish_date")[0].childNodes[0]
      .nodeValue,
    description: book.getElementsByTagName("description")[0].childNodes[0]
      .nodeValue,
  });
}
import React, { useEffect, useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { connect } from "react-redux";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableRow from "@material-ui/core/TableRow";
import { Icon } from "@material-ui/core";
import {
  CallMade,
  CallReceived,
  FiberManualRecord,
  Error,
} from "@material-ui/icons";

function createData(message, timestamp, type) {
  return { message, timestamp, type };
}

const rows = [];

const useStyles = makeStyles((theme) => ({
  root: {
    width: "100%",
  },
  icons: {
    fontSize: 18,
  },
  connecting: {
    color: "#11FF0C",
  },
  connected: {
    color: "#11FF0C",
  },
  disconnecting: {
    color: "#FF5050",
  },
  disconnected: {
    color: "#FF5050",
  },
  error: {
    color: "#FF5050",
  },
  request: {
    // color: "#11FF0C"
  },
  response: {
    // color: "#11FF0C"
  },
}));

function Logger(props) {
  const { v4: uuidv4 } = require("uuid");
  const classes = useStyles();
  const [theLog, addLog] = useState([]);

  useEffect(() => {
    if (typeof props.log === "function") {
      const values = props.log();
      addLog([
        ...theLog,
        createData(values.message, values.timestamp, values.type),
      ]);
    }
  }, [props.log]);

  function createData(message, timestamp, type) {
    console.log("s");
    return { message, timestamp, type };
  }

  return (
    <div>
      {props.showLog ? (
        <div className={classes.root}>
          <Table aria-labelledby="tableTitle" size="small">
            <TableBody>
              {theLog.map((row, index) => {
                return (
                  <TableRow
                    key={uuidv4()}
                    hover
                    role="checkbox"
                    tabIndex={-1}
                    key={row.timestamp}
                  >
                    <TableCell padding="checkbox">
                      <Icon>
                        {row.type === "connecting" && (
                          <FiberManualRecord
                            className={`${classes.connecting} ${classes.icons}`}
                          />
                        )}
                        {row.type === "connected" && (
                          <FiberManualRecord
                            className={`${classes.connected} ${classes.icons}`}
                          />
                        )}
                        {row.type === "disconnecting" && (
                          <FiberManualRecord
                            className={`${classes.disconnecting} ${classes.icons}`}
                          />
                        )}
                        {row.type === "disconnected" && (
                          <FiberManualRecord
                            className={`${classes.disconnected} ${classes.icons}`}
                          />
                        )}
                        {row.type === "error" && (
                          <Error
                            className={`${classes.error} ${classes.icons}`}
                          />
                        )}
                        {row.type === "request" && (
                          <CallMade
                            className={`${classes.request} ${classes.icons}`}
                          />
                        )}
                        {row.type === "response" && (
                          <CallReceived
                            className={`${classes.response} ${classes.icons}`}
                          />
                        )}
                      </Icon>
                    </TableCell>
                    <TableCell>{row.message}</TableCell>
                    <TableCell>{row.timestamp}</TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </div>
      ) : null}
    </div>
  );
}

function mapStateToProps(state) {
  return {
    log: state.reducer.log,
    showLog: state.reducer.showLog,
  };
}

export default connect(mapStateToProps, null)(Logger);
从“/books.types”导入{booksActionTypes};
导出常量showLog=()=>({
类型:booksActionTypes.SHOWLOG,
});
导出常量setLogMessage=(日志)=>({
类型:booksActionTypes.LOG_消息,
有效载荷:日志,
});
导出常量clearPosts=()=>({
类型:booksActionTypes.CLEAR_POSTS,
});
导出常量requestStart=()=>({
类型:booksActionTypes.REQUEST\u START,
});
导出const requestSuccess=(booksList)=>({
类型:booksActionTypes.REQUEST\u SUCCESS,
有效载荷:图书列表,
});
导出常量请求失败=(errMsg)=>({
类型:booksActionTypes.REQUEST\u失败,
有效载荷:errMsg,
});
导出常量actionCreators={
//“应用程序URL”:http://localhost:51374", http://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?title=dep&author=&genre=&price=
//“sslPort”:44378
requestBooks:(book)=>async(dispatch,getState)=>{
分派(requestStart());
派遣(
setLogMessage(()=>({
消息:“开始图书搜索…”,
时间戳:
新建日期().getHours()+
"-" +
新建日期().getMinutes()+
"-" +
新建日期().getSeconds(),
类型:“正在连接”,
}))
);
var queryString=Object.keys(书本)
.map((键)=>{
返回encodeURIComponent(key)+“=”+encodeURIComponent(book[key]);
})
.加入(“&”);
变量url=
"htftp://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?" +
询问;
派遣(
setLogMessage(()=>({
消息:“搜索url为:”,
时间戳:
新建日期().getHours()+
"-" +
新建日期().getMinutes()+
"-" +
新建日期().getSeconds(),
类型:“正在连接”,
}))
);
派遣(
setLogMessage(()=>({
信息:“Sdsadsasada:”,
时间戳:
新建日期().getHours()+
"-" +
新建日期().getMinutes()+
"-" +
新建日期().getSeconds(),
类型:“正在连接”,
}))
);
等待获取(url)
.然后((res)=>res.json())
。然后((xml)=>{
调度(requestSuccess(xml));
})
.catch((errMsg)=>{
console.log(errMsg);
调度(请求失败(errMsg));
获取(“books.xml”)
.然后((res)=>res.text())
.then((xmlString)=>getFromLocalDatabase(dispatch,xmlString,book))
.catch((错误)=>{
调度(请求失败(errMsg));
});
});
},
};
函数getFromLocalDatabase(分派、xmlFile、book){
var parser=new window.DOMParser();
var xmlDoc=parser.parseFromString(xmlFile,“text/xml”);
var books=xmlDoc.documentElement.childNodes;
var-map=[];
for(var i=0;i=0){
发回本书(地图、书籍[i]);
}
if(book.title&&title.indexOf(book.title.toLowerCase())>=0){
发回本书(地图、书籍[i]);
}
if(book.genre&&genre.indexOf(book.genre.toLowerCase())>=0){
发回本书(地图、书籍[i]);
}
if(book.price&&price.indexOf(book.price.toLowerCase())>=0){
发回本书(地图、书籍[i]);
}
如果(
出版日期&&
publish_date.indexOf(book.publish_date.toLowerCase())>=0
) {
发回本书(地图、书籍[i]);
}
如果(
书名&&
description.indexOf(book.description.toLowerCase())>=0
) {
发回本书(地图、书籍[i]);
}
}
调度(请求成功(map));
}
函数sendBackThisBook(地图、书本){
var index=map.findIndex((x)=>x.id==book.getAttribute(“id”);
如果(索引!=-1){
log(`existskipping`,book.getAttribute(“id”);
返回;
}
地图推送({
id:book.getAttribute(“id”),
标题:book.getElementsByTagName(“标题”)[0]。子节点[0]。节点值,
作者:book.getElementsByTagName(“作者”)[0]。子节点[0]。节点值,
类型:book.getElementsByTagName(“类型”)[0]。子节点[0]。节点值,
价格:book.getElementsByTagName(“价格”)[0]。childNodes[0]。nodeValue,
发布日期:book.getElementsByTagName(“发布日期”)[0]。子节点[0]
诺德瓦卢先生,
描述:book.getElementsByTagName(“描述”)[0].childNodes[0]
诺德瓦卢先生,
});
}
这是接收Redux存储状态的类:

import { booksActionTypes } from "./books.types";

export const showLog = () => ({
  type: booksActionTypes.SHOWLOG,
});

export const setLogMessage = (log) => ({
  type: booksActionTypes.LOG_MESSAGE,
  payload: log,
});

export const clearPosts = () => ({
  type: booksActionTypes.CLEAR_POSTS,
});

export const requestStart = () => ({
  type: booksActionTypes.REQUEST_START,
});

export const requestSuccess = (booksList) => ({
  type: booksActionTypes.REQUEST_SUCCESS,
  payload: booksList,
});

export const requestFailure = (errMsg) => ({
  type: booksActionTypes.REQUEST_FAILURE,
  payload: errMsg,
});

export const actionCreators = {
  // "applicationUrl": "http://localhost:51374", http://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?title=dep&author=&genre=&price=
  // "sslPort": 44378
  requestBooks: (book) => async (dispatch, getState) => {
    dispatch(requestStart());
    dispatch(
      setLogMessage(() => ({
        message: "Starting books search..",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );

    var queryString = Object.keys(book)
      .map((key) => {
        return encodeURIComponent(key) + "=" + encodeURIComponent(book[key]);
      })
      .join("&");
    var url =
      "htftp://erikswed.ddns.net:8965/api/BooksXml/getbooks/fromall/?" +
      queryString;
    dispatch(
      setLogMessage(() => ({
        message: "Search url is: ",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );
    dispatch(
      setLogMessage(() => ({
        message: "Sdsadsasada: ",
        timestamp:
          new Date().getHours() +
          "-" +
          new Date().getMinutes() +
          "-" +
          new Date().getSeconds(),
        type: "connecting",
      }))
    );
    await fetch(url)
      .then((res) => res.json())
      .then((xml) => {
        dispatch(requestSuccess(xml));
      })
      .catch((errMsg) => {
        console.log(errMsg);
        dispatch(requestFailure(errMsg));
        fetch("books.xml")
          .then((res) => res.text())
          .then((xmlString) => getFromLocalDatabas(dispatch, xmlString, book))
          .catch((err) => {
            dispatch(requestFailure(errMsg));
          });
      });
  },
};
function getFromLocalDatabas(dispatch, xmlFile, book) {
  var parser = new window.DOMParser();
  var xmlDoc = parser.parseFromString(xmlFile, "text/xml");
  var books = xmlDoc.documentElement.childNodes;
  var map = [];
  for (var i = 0; i < books.length; i++) {
    var author = books[i]
      .getElementsByTagName("author")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var title = books[i]
      .getElementsByTagName("title")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var genre = books[i]
      .getElementsByTagName("genre")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var price = books[i]
      .getElementsByTagName("price")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var publish_date = books[i]
      .getElementsByTagName("publish_date")[0]
      .childNodes[0].nodeValue.toLowerCase();
    var description = books[i]
      .getElementsByTagName("description")[0]
      .childNodes[0].nodeValue.toLowerCase();

    if (book.author && author.indexOf(book.author.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.title && title.indexOf(book.title.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.genre && genre.indexOf(book.genre.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (book.price && price.indexOf(book.price.toLowerCase()) >= 0) {
      sendBackThisBook(map, books[i]);
    }
    if (
      book.publish_date &&
      publish_date.indexOf(book.publish_date.toLowerCase()) >= 0
    ) {
      sendBackThisBook(map, books[i]);
    }
    if (
      book.description &&
      description.indexOf(book.description.toLowerCase()) >= 0
    ) {
      sendBackThisBook(map, books[i]);
    }
  }
  dispatch(requestSuccess(map));
}

function sendBackThisBook(map, book) {
  var index = map.findIndex((x) => x.id == book.getAttribute("id"));
  if (index != -1) {
    console.log(`exist skipping `, book.getAttribute("id"));
    return;
  }
  map.push({
    id: book.getAttribute("id"),
    title: book.getElementsByTagName("title")[0].childNodes[0].nodeValue,
    author: book.getElementsByTagName("author")[0].childNodes[0].nodeValue,
    genre: book.getElementsByTagName("genre")[0].childNodes[0].nodeValue,
    price: book.getElementsByTagName("price")[0].childNodes[0].nodeValue,
    publish_date: book.getElementsByTagName("publish_date")[0].childNodes[0]
      .nodeValue,
    description: book.getElementsByTagName("description")[0].childNodes[0]
      .nodeValue,
  });
}
import React, { useEffect, useState } from "react";
import { makeStyles } from "@material-ui/core/styles";
import { connect } from "react-redux";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableRow from "@material-ui/core/TableRow";
import { Icon } from "@material-ui/core";
import {
  CallMade,
  CallReceived,
  FiberManualRecord,
  Error,
} from "@material-ui/icons";

function createData(message, timestamp, type) {
  return { message, timestamp, type };
}

const rows = [];

const useStyles = makeStyles((theme) => ({
  root: {
    width: "100%",
  },
  icons: {
    fontSize: 18,
  },
  connecting: {
    color: "#11FF0C",
  },
  connected: {
    color: "#11FF0C",
  },
  disconnecting: {
    color: "#FF5050",
  },
  disconnected: {
    color: "#FF5050",
  },
  error: {
    color: "#FF5050",
  },
  request: {
    // color: "#11FF0C"
  },
  response: {
    // color: "#11FF0C"
  },
}));

function Logger(props) {
  const { v4: uuidv4 } = require("uuid");
  const classes = useStyles();
  const [theLog, addLog] = useState([]);

  useEffect(() => {
    if (typeof props.log === "function") {
      const values = props.log();
      addLog([
        ...theLog,
        createData(values.message, values.timestamp, values.type),
      ]);
    }
  }, [props.log]);

  function createData(message, timestamp, type) {
    console.log("s");
    return { message, timestamp, type };
  }

  return (
    <div>
      {props.showLog ? (
        <div className={classes.root}>
          <Table aria-labelledby="tableTitle" size="small">
            <TableBody>
              {theLog.map((row, index) => {
                return (
                  <TableRow
                    key={uuidv4()}
                    hover
                    role="checkbox"
                    tabIndex={-1}
                    key={row.timestamp}
                  >
                    <TableCell padding="checkbox">
                      <Icon>
                        {row.type === "connecting" && (
                          <FiberManualRecord
                            className={`${classes.connecting} ${classes.icons}`}
                          />
                        )}
                        {row.type === "connected" && (
                          <FiberManualRecord
                            className={`${classes.connected} ${classes.icons}`}
                          />
                        )}
                        {row.type === "disconnecting" && (
                          <FiberManualRecord
                            className={`${classes.disconnecting} ${classes.icons}`}
                          />
                        )}
                        {row.type === "disconnected" && (
                          <FiberManualRecord
                            className={`${classes.disconnected} ${classes.icons}`}
                          />
                        )}
                        {row.type === "error" && (
                          <Error
                            className={`${classes.error} ${classes.icons}`}
                          />
                        )}
                        {row.type === "request" && (
                          <CallMade
                            className={`${classes.request} ${classes.icons}`}
                          />
                        )}
                        {row.type === "response" && (
                          <CallReceived
                            className={`${classes.response} ${classes.icons}`}
                          />
                        )}
                      </Icon>
                    </TableCell>
                    <TableCell>{row.message}</TableCell>
                    <TableCell>{row.timestamp}</TableCell>
                  </TableRow>
                );
              })}
            </TableBody>
          </Table>
        </div>
      ) : null}
    </div>
  );
}

function mapStateToProps(state) {
  return {
    log: state.reducer.log,
    showLog: state.reducer.showLog,
  };
}

export default connect(mapStateToProps, null)(Logger);
import React,{useffect,useState}来自“React”;
从“@material ui/core/styles”导入{makeStyles}”;
从“react redux”导入{connect};
从“@物料界面/核心/表格”导入表格;
从“@material ui/core/TableBody”导入表体;
导入表单元格