Javascript 在ReactJS中使用单独的方法填充渲染方法

Javascript 在ReactJS中使用单独的方法填充渲染方法,javascript,reactjs,firebase,google-cloud-firestore,Javascript,Reactjs,Firebase,Google Cloud Firestore,好的,大家都知道单独的映射可以在React render方法中渲染组件,如下所示: var listOfService = ['A', 'B', 'C', 'D', 'E']; const listItems = listOfService.map((singleItem) => <a className="style_class">{singleItem}</a> ); 所以我尝试了这个方法,但不起作用,我写了一些控制台日志,数据输入正确。首先,我得到整

好的,大家都知道单独的映射可以在React render方法中渲染组件,如下所示:

var listOfService = ['A', 'B', 'C', 'D', 'E'];
const listItems = listOfService.map((singleItem) =>
    <a className="style_class">{singleItem}</a>
);

所以我尝试了这个方法,但不起作用,我写了一些控制台日志,数据输入正确。首先,我得到整个“
提供者
”文档数组,提供者列表作为“
快照
”传递,因此我使用另一个函数循环通过快照,该函数获取一个名为
文档
的文档,然后将其推入名为
详细信息
变量中,这是一个数组数组,但是!它不工作,数组没有被填充,即使数据在那里,因此我无法映射,关于如何实现这一点有什么想法吗?

您需要分离数据加载和数据呈现,因为检索数据是异步的,呈现需要是同步的

例如,在您的情况下,您正在将详细信息推入
然后
回调中的数组-这将对主函数发生
async
,因此当您调用
details.map
时,它仍然是空的(回调没有启动来填充它)

相反,您可以加载数据并将其存储在状态中,然后在数据可用时进行渲染。就我个人而言,我更喜欢
async/await
,但在承诺上使用
then
也可以实现同样的逻辑:

const [details, setDetails] = useState([]);

// Load the data on initial load or setup the effect to fire when reload is needed
useEffect(() => {

  // Async function that loads the data and sets the state once ready
  const loadData = async () => {
    const details = [];
    try {
      const snapshot = await db.collection('providers').get();
      snapshot.forEach((doc) => {
        details.push([
          // your details stuff
        ]);
      }
    } catch (ex) {
      // Handle any loading exceptions
    }

    setDetails(details);
  }
}, [])


// Render the available details, you could also add conditional rendering to check
// if the details are available or not yet
return (
  <div>
    {details.map((singleDetail) => (
      <Service details={singleDetail} />
    )};
  </div>
);
const[details,setDetails]=useState([]);
//在初始加载时加载数据,或设置在需要重新加载时触发的效果
useffect(()=>{
//异步函数,用于加载数据并设置就绪后的状态
const loadData=async()=>{
常量详细信息=[];
试一试{
const snapshot=await db.collection('providers').get();
snapshot.forEach((doc)=>{
推送([
//你的细节资料
]);
}
}捕获(ex){
//处理任何加载异常
}
设置详细信息(详细信息);
}
}, [])
//渲染可用的详细信息时,还可以添加条件渲染以进行检查
//是否有详细信息
返回(
{details.map((singleDetail)=>(
)};
);

如果您使用的是React类而不是功能组件,则可以从
componentDidMount
调用加载,并在加载后仍然设置状态,然后在渲染时映射状态数据。

我使用ReactDOM.render方法找到了解决方案

首先创建一个全局数组:

var Services = [];
然后添加一个可以放置和渲染数组的DOM元素:

<div className="row d-flex justify-content-center" id='service-div'>

</div>
现在在这个方法中,只需填充数组,然后使用ReactDOM.render方法将其渲染到给定的DOM元素

async renderServices() {

    let history = this.props.history; //in case the method can't access the history

    let db = firebase.firestore();
    selectedServices = this.props.location.state.selectedServices;

    var database = firebase.database();

    db.collection('providers').where('services', 'array-contains-any',
        selectedServices).get()
        .then(function (snapshot) {
            let idCount = 0;
            snapshot.forEach(function (doc) {

                let tempDetails = [];
                tempDetails.push(
                    doc.data().owner_name,
                    doc.data().experience,
                    doc.data().charges,
                    doc.data().address,
                    doc.data().home_service,
                    doc.data().highlights,
                    doc.data().certifications,
                    doc.data().specialty,
                    doc.data().facility,
                    doc.data().services,
                    doc.data().call_extension,
                    idCount.toString()
                );

                Services.push(<Service details={tempDetails} history={history} />); //adding the Service Component into a list
                idCount++;
            });
            ReactDOM.render(<div>{Services}</div>, document.getElementById('service-div')); //now rendering the entire list into the div
        }).catch(function (error) {
            console.log(error);

        });



}
async renderServices(){
让history=this.props.history;//如果方法无法访问历史记录
设db=firebase.firestore();
selectedServices=this.props.location.state.selectedServices;
var database=firebase.database();
db.collection('providers')。其中('services','array包含any',
selectedServices.get()
.then(功能(快照){
设idCount=0;
snapshot.forEach(函数(文档){
设tempDetails=[];
临时推送(
文档数据()所有者名称,
文档数据()经验,
单据数据()费用,
doc.data().地址,
doc.data().home_服务,
doc.data()突出显示,
文档数据()证书,
doc.data().speciality,
doc.data().facility,
doc.data()服务,
doc.data().调用扩展名,
idCount.toString()
);
Services.push();//将服务组件添加到列表中
idCount++;
});
ReactDOM.render({Services},document.getElementById('service-div'));//现在将整个列表呈现到div中
}).catch(函数(错误){
console.log(错误);
});
}

你说的“我知道你不能在循环或if语句中使用JSX”是什么意思?你已经从循环中返回了JSX,所以你确定这就是你的意思吗?我对firestore没有太多经验,但这样的操作通常是异步的(基于你对
的使用,那么
我会说就是这样)。当你试图偶然地做
映射时,
details
仍然是一个空数组吗?@Brianthonpson yea细节数组保持为空,它的werid。我在details.push()前面写了console.log行它显示了所有数据,但似乎无法将相同的数据传递给细节数组。这就像某种阻塞和超出范围的问题创建jsx元素数组,即代码中的服务组件。将文档作为细节传递给服务,并从函数返回细节数组。好的,我做了类似的事情,它似乎加载了所有数据但是它并不像你在代码中写的那样映射,让我看看这是怎么回事
ComponentDidMount(){
this.renderServices();}
async renderServices() {

    let history = this.props.history; //in case the method can't access the history

    let db = firebase.firestore();
    selectedServices = this.props.location.state.selectedServices;

    var database = firebase.database();

    db.collection('providers').where('services', 'array-contains-any',
        selectedServices).get()
        .then(function (snapshot) {
            let idCount = 0;
            snapshot.forEach(function (doc) {

                let tempDetails = [];
                tempDetails.push(
                    doc.data().owner_name,
                    doc.data().experience,
                    doc.data().charges,
                    doc.data().address,
                    doc.data().home_service,
                    doc.data().highlights,
                    doc.data().certifications,
                    doc.data().specialty,
                    doc.data().facility,
                    doc.data().services,
                    doc.data().call_extension,
                    idCount.toString()
                );

                Services.push(<Service details={tempDetails} history={history} />); //adding the Service Component into a list
                idCount++;
            });
            ReactDOM.render(<div>{Services}</div>, document.getElementById('service-div')); //now rendering the entire list into the div
        }).catch(function (error) {
            console.log(error);

        });



}