反应渲染附加而不是替换内容

时间:2020-04-09 22:03:47

标签: reactjs

我有一个contentEditable反应组件,该组件根据各种状态变化进行更新。状态项包含文本框中的段落。这些是React组件。以下是3个段落的示例状态值。

enter image description here

相应的文本框可能如下所示:

enter image description here

单击按钮即可转换为React组件。当我用新的段落更新HTML状态项时,我有一些奇怪的行为。它会再次添加新段落,而不是替换新段落:它应该始终输出html状态项中包含的内容。

enter image description here

看来我现在有5个段落组件。但是我没有,我应该只看到以下四个项目:

enter image description here

我的render方法只是状态中通过HTML项的映射。有点难以解释,但希望它是有道理的。我在想这与React如何比较组件有关?

相关代码

// Method to update state with new HTML components
componentDidUpdate = prevProps => {
  if (prevProps.isSubmitted !== this.props.isSubmitted) {
    this.handleStateUpdate({
      html: this.createHtml()
    });
  }
};

// createHTML function is something like this, I have excluded unimportant code
createHtml = () =>
  this.props.paragraphDict.map((paragraph, key) => {
    const flaggedWords = Object.keys(paragraph);
    return (
      <Paragraph key={key}>
        {flaggedWords.map(wordId => (
          <Word key={wordId} {...props} />
        ))}
      </Paragraph>
    );
  });

// Render
render = () => {
  const { html } = this.state;

  return (
    <StyledEditor
      ref={this.el}
      contentEditable={true}
      suppressContentEditableWarning={true}
      spellCheck={false}
      onBlur={({ target }) => this.handleEditorBlur(target.innerHTML)}
    >
      {html && html.map(item => item)}
    </StyledEditor>
  );
};

2 个答案:

答案 0 :(得分:0)

我会以评论的形式发表,但我不能这样,我会在这里问-您能否确认以下内容:

>     @Override
>         public boolean allowRerouteFrom(Point offRoutePoint) {
>             navigationView.stopNavigation();//I do this, cuz if not, the listenner still continue working and the application crashes 
>            
>             //Route Request, Im using a microservice and doing the request with OkHttpClient
>     
>             OkHttpClient client= new OkHttpClient();
>             String url= ....
>     .....
>                     if (response.isSuccessful()){
>                         final String myResponse = response.body().string().trim();
>                         PruebaNavegacion.this.runOnUiThread(new Runnable() {
>                             @Override
>                             public void run() {
>                                 try {
>                                     JSONObject jsonObject= new ...
>     ...
>                                                 pointsrecalruta.add(Point.fromLngLat(Double.parseDouble(longitud),
> Double.parseDouble(latitud)));
//Here I read the points of the new route that i want follow
>      
>                                     }
>     //Then I use MapboxMapMatching function to fetch the  new route
>                                     
>             List<Point> pointsrutarecal = new ArrayList<>();
>                                     pointsrutarecal=pointsrecalruta.subList(0,pointsrecalruta.size()-1);
>                                     DirectionsRoute route = null;
>                                     //inicioArray=inicio;
>                                     //finArray=fin;
>                                     MapboxMapMatching.builder()
>                                             .accessToken(theMapboxToken)
>                                             .coordinates(pointsrutarecal)
>                                             .waypointIndices(0,pointsrutarecal.size()-1)
>                                             .steps(true)
>                                             .voiceUnits("metric")
>                                             .language("es")
>                                             .voiceInstructions(true)
>                                             .bannerInstructions(true)
>                                             .profile(DirectionsCriteria.PROFILE_DRIVING)
>                                             .build()
>                                             .enqueueCall(new Callback<MapMatchingResponse>() {
>     
>                                                 @Override
>                                                 public void onResponse(Call<MapMatchingResponse> call,
> Response<MapMatchingResponse> response) {
>     
>                                                     if (response.isSuccessful()) {
>                                                         Log.i("Mapa","iEntre al reponse succesfull");
>                                                         if(response.code()==200) {
>                                                             Log.i("Mapa","iEntre al reponse succesfull,code 200");
>     
>                                                             try {
>                                                                 DirectionsRoute route =
> response.body().matchings().get(0).toDirectionRoute();
>     
>                                                                 // progressDialog.dismiss();
>                                                                 //rutarecal=route;
>                                                                 // Create new options with map matching response route
>     
>                                                                 NavigationViewOptions options = NavigationViewOptions.builder()
>                                                                         //.routeListener(PruebaNavegacion.this)
>                                                                         //.directionsRoute(route)
>                                                                         .navigationListener(PruebaNavegacion.this)
>                                                                         .directionsRoute(route)
>                                                                         .shouldSimulateRoute(false)
>                                                                         .progressChangeListener(PruebaNavegacion.this)
>                                                                         .instructionListListener(PruebaNavegacion.this)
>                                                                         .speechAnnouncementListener(PruebaNavegacion.this)
>                                                                         .routeListener(PruebaNavegacion.this)
>                                                                         .bannerInstructionsListener(PruebaNavegacion.this)
>                                                                 //setBottomSheetCallback(options);
>                                                                 //setupNightModeFab();
>                                                                         .build();
>                                                                 navigationView.startNavigation(options);
>     
>                                                             }catch (Exception e){
>                                                                 Toast.makeText(PruebaNavegacion.this, "Ruta invalida",
> Toast.LENGTH_SHORT).show();
>     
>                                                             }
>                                                         }
>                                                         else {
>                                                             Log.i("Mapa","iEntre al reponse succesfull code no 200");
>                                                             Log.e("mapa","MapboxMapMatching failed with "+response.code());
>                                                         }
>                                                     }
>     
>                                                     else{
>                                                       //Anything happend here
>                                                     }
>                                                 }
>     
>                                                 @Override
>                                                 public void onFailure(Call<MapMatchingResponse> call, Throwable throwable) {
>                                                     Log.i("Mapa","iEntre al reponse failure");
>                                                     Log.e("Error mapa:", "MapboxMapMatching error"+throwable.toString());
>                                                 }
>                                             });
>     
>                                     //Fin del mapmatching
>     
>                                     //progressDialog.dismiss();
>                                 } catch (JSONException e) {
>                                     e.printStackTrace();
>                                 }
>     
>                                
>                             }
>                         });
>     
>                     }
>                 }
>             });
>         
>     // Ignore internal routing, allowing MapboxMapMatching call
>             return false;
>         }

createHtml = () => this.props.paragraphDict.map((paragraph, key) => { const flaggedWords = Object.keys(paragraph); return ( <Paragraph key={key}> {flaggedWords.map(wordId => ( <Word key={wordId} {...props} /> ))} </Paragraph> ); }); :这是一个数组吗?名称暗示不是,但地图暗示是。也许是要命名为this.props.paragraphDict

我假设它是一个数组,在这种情况下,paragraphDicts将是该数组中每个项目的索引。您正在将此索引作为key组件的密钥传递,这可能是导致问题的原因。

您可以尝试将Paragraph替换为key={key}吗? (或该段落的任何其他唯一标识符)

答案 1 :(得分:0)

问题与键无关。为了解决这个问题,我本质上增加了一个基于当前提交状态的条件元素。然后,将使用新内容正确地重新渲染可编辑字段,如下所示:


return isSubmitting ? (
    <StyledEditor />
    ) : (
    <StyledEditor
        ref={this.el}
        contentEditable={true}
        suppressContentEditableWarning={true}
        spellCheck={false}
        onInput={({ target }) => this.handleEditorBlur(target.innerHTML)}
    >
        {html}
    </StyledEditor>