我有一个contentEditable
反应组件,该组件根据各种状态变化进行更新。状态项包含文本框中的段落。这些是React组件。以下是3个段落的示例状态值。
相应的文本框可能如下所示:
单击按钮即可转换为React组件。当我用新的段落更新HTML
状态项时,我有一些奇怪的行为。它会再次添加新段落,而不是替换新段落:它应该始终输出html
状态项中包含的内容。
看来我现在有5个段落组件。但是我没有,我应该只看到以下四个项目:
我的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>
);
};
答案 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>